From 510d736db9c69b2d12d491de7c986fbe17b2be46 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 11 Dec 2024 14:57:57 -0500 Subject: [PATCH 1/5] INTPYTHON-442 Add linting to repo --- .pre-commit-config.yaml | 4 +- ...ystack_self_reflecting_Cooking_agent.ipynb | 32 +- ...agent_fireworks_ai_langchain_mongodb.ipynb | 6 +- .../agentchat_RetrieveChat_mongodb.ipynb | 2 - ...ant_with_langgraph_langchain_mongodb.ipynb | 71 +- ...rbnb_agent_openai_llamaindex_mongodb.ipynb | 3675 ++++---- ...nt_agentic_chatbot_langgraph_mongodb.ipynb | 87 +- notebooks/agents/crewai-mdb-agg.ipynb | 5 +- ...claude_3_5_sonnet_llamaindex_mongodb.ipynb | 10 +- ...d_ai_agent_openai_llamaindex_mongodb.ipynb | 10 +- ...gentic_chatbot_with_langgraph_claude.ipynb | 23 +- ...rking_memory_with_tavily_and_mongodb.ipynb | 11 +- .../mongodb_with_aws_bedrock_agent.ipynb | 7 +- notebooks/evals/angle-embeddings-eval.ipynb | 9 +- notebooks/evals/openai-embeddings-eval.ipynb | 9 +- notebooks/evals/ragas-evaluation.ipynb | 32 +- .../evals/voyageai-embeddings-eval.ipynb | 4 +- .../tensorflow_mongodbcharts_horoscopes.ipynb | 8 +- .../SwigMenu_Playwright_OpenAI_MongoDB.ipynb | 6 +- ...spatialqueries_vectorsearch_spritzes.ipynb | 3 +- .../rag/Haystack_MongoDB_Atlas_RAG.ipynb | 16 +- ...ner_PlaywrightLlamaIndexVectorSearch.ipynb | 22 +- .../rag/anthropic_mongodb_pam_ai_stack.ipynb | 5 +- ...amaIndex_and_MongoDB_Vector_Database.ipynb | 6 +- ...ngodb_openai_langchain_POLM_AI_Stack.ipynb | 9 +- .../graphrag_with_mongodb_and_openai.ipynb | 18 +- ...ack_mongodb_cooking_advisor_pipeline.ipynb | 23 +- .../rag/mongodb-langchain-cache-memory.ipynb | 16 +- .../naive_rag_implemenation_llamaindex.ipynb | 8 +- notebooks/rag/openai_text_3_emebdding.ipynb | 2 +- .../rag_chatbot_with_cohere_and_mongodb.ipynb | 7 +- notebooks/rag/rag_chunking_strategies.ipynb | 26 +- ...ngodb_llama3_huggingface_open_source.ipynb | 7 +- ...rag_pipeline_kerasnlp_mongodb_gemma2.ipynb | 11 +- ...g_with_gemma2_2b_mongodb_open_models.ipynb | 33 +- .../rag_with_gemma2_mongodb_open_models.ipynb | 8 +- .../rag_with_hugging_face_gemma_mongodb.ipynb | 4 +- ...rying_mongodb_unstructured_langgraph.ipynb | 48 +- ...ed_vectors_using_cohere_mongodb_beir.ipynb | 22 +- ...trival_techniques_mongondb_langchain.ipynb | 7657 +++++++++-------- ...or_ingestion_with_cohere_and_mongodb.ipynb | 10 +- ...rieval_strategies_mongodb_llamaindex.ipynb | 4361 +++++----- ...tegies_mongodb_llamaindex_togetherai.ipynb | 17 +- ...tion_From_RAG_to_Agents_with_MongoDB.ipynb | 10 +- ruff.toml | 32 + ...anagement_for_International_Shipping.ipynb | 68 +- .../embeddings_generator/create_embeddings.py | 24 +- tools/embeddings_generator/utils.py | 2 +- ...unction_calling_mongodb_as_a_toolbox.ipynb | 7 +- 49 files changed, 8255 insertions(+), 8238 deletions(-) create mode 100644 ruff.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e2309fe..9bb7700 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: # Ruff version. rev: v0.8.2 hooks: - # - id: ruff - # args: ["--fix", "--show-fixes"] + - id: ruff + args: ["--fix", "--show-fixes"] - id: ruff-format exclude: notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb diff --git a/notebooks/agents/MongoDB_Haystack_self_reflecting_Cooking_agent.ipynb b/notebooks/agents/MongoDB_Haystack_self_reflecting_Cooking_agent.ipynb index cd6c2d4..dc1b9f8 100644 --- a/notebooks/agents/MongoDB_Haystack_self_reflecting_Cooking_agent.ipynb +++ b/notebooks/agents/MongoDB_Haystack_self_reflecting_Cooking_agent.ipynb @@ -268,20 +268,19 @@ }, "outputs": [], "source": [ - "from haystack import Pipeline, Document\n", - "from haystack.document_stores.types import DuplicatePolicy\n", - "from haystack.components.writers import DocumentWriter\n", - "from haystack.components.generators import OpenAIGenerator\n", + "from bson import json_util\n", + "from haystack import Document, Pipeline\n", "from haystack.components.builders.prompt_builder import PromptBuilder\n", - "from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder\n", - "from haystack_integrations.document_stores.mongodb_atlas import (\n", - " MongoDBAtlasDocumentStore,\n", - ")\n", + "from haystack.components.embedders import OpenAIDocumentEmbedder, OpenAITextEmbedder\n", + "from haystack.components.generators import OpenAIGenerator\n", + "from haystack.components.writers import DocumentWriter\n", + "from haystack.document_stores.types import DuplicatePolicy\n", "from haystack_integrations.components.retrievers.mongodb_atlas import (\n", " MongoDBAtlasEmbeddingRetriever,\n", ")\n", - "from datasets import load_dataset\n", - "from bson import json_util\n", + "from haystack_integrations.document_stores.mongodb_atlas import (\n", + " MongoDBAtlasDocumentStore,\n", + ")\n", "\n", "dataset = {\n", " \"train\": [\n", @@ -1156,8 +1155,9 @@ }, "outputs": [], "source": [ - "from colorama import Fore\n", "from typing import List\n", + "\n", + "from colorama import Fore\n", "from haystack import component\n", "\n", "\n", @@ -1167,9 +1167,8 @@ " def run(self, replies: List[str]):\n", " if \"DONE\" in replies[0]:\n", " return {\"recipe\": replies[0].replace(\"done\", \"\")}\n", - " else:\n", - " print(Fore.RED + \"Not done yet, could make recipe more efficient\")\n", - " return {\"recipe_to_check\": replies[0]}" + " print(Fore.RED + \"Not done yet, could make recipe more efficient\")\n", + " return {\"recipe_to_check\": replies[0]}" ] }, { @@ -1555,9 +1554,10 @@ } ], "source": [ - "from pymongo import MongoClient\n", - "import json\n", "import datetime\n", + "import json\n", + "\n", + "from pymongo import MongoClient\n", "\n", "query = \"How can I cook a lasagne?\"\n", "result = reflecting_rag_pipeline.run(\n", diff --git a/notebooks/agents/agent_fireworks_ai_langchain_mongodb.ipynb b/notebooks/agents/agent_fireworks_ai_langchain_mongodb.ipynb index f2e1466..c2f777c 100644 --- a/notebooks/agents/agent_fireworks_ai_langchain_mongodb.ipynb +++ b/notebooks/agents/agent_fireworks_ai_langchain_mongodb.ipynb @@ -452,8 +452,8 @@ }, "outputs": [], "source": [ - "from langchain_openai import OpenAIEmbeddings\n", "from langchain_mongodb import MongoDBAtlasVectorSearch\n", + "from langchain_openai import OpenAIEmbeddings\n", "\n", "embedding_model = OpenAIEmbeddings(model=\"text-embedding-3-small\", dimensions=256)\n", "\n", @@ -556,8 +556,8 @@ "outputs": [], "source": [ "from langchain.agents import tool\n", - "from langchain_community.document_loaders import ArxivLoader\n", "from langchain.tools.retriever import create_retriever_tool\n", + "from langchain_community.document_loaders import ArxivLoader\n", "\n", "\n", "# Custom Tool Definiton\n", @@ -727,8 +727,8 @@ }, "outputs": [], "source": [ - "from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory\n", "from langchain.memory import ConversationBufferMemory\n", + "from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory\n", "\n", "\n", "def get_session_history(session_id: str) -> MongoDBChatMessageHistory:\n", diff --git a/notebooks/agents/agentchat_RetrieveChat_mongodb.ipynb b/notebooks/agents/agentchat_RetrieveChat_mongodb.ipynb index bf7704d..f683d15 100644 --- a/notebooks/agents/agentchat_RetrieveChat_mongodb.ipynb +++ b/notebooks/agents/agentchat_RetrieveChat_mongodb.ipynb @@ -54,10 +54,8 @@ } ], "source": [ - "import json\n", "import os\n", "\n", - "import autogen\n", "from autogen import AssistantAgent\n", "from autogen.agentchat.contrib.retrieve_user_proxy_agent import RetrieveUserProxyAgent\n", "\n", diff --git a/notebooks/agents/agentic_rag_factory_safety_assistant_with_langgraph_langchain_mongodb.ipynb b/notebooks/agents/agentic_rag_factory_safety_assistant_with_langgraph_langchain_mongodb.ipynb index 624b824..5ef9c7b 100644 --- a/notebooks/agents/agentic_rag_factory_safety_assistant_with_langgraph_langchain_mongodb.ipynb +++ b/notebooks/agents/agentic_rag_factory_safety_assistant_with_langgraph_langchain_mongodb.ipynb @@ -35,8 +35,8 @@ }, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "import os\n", "\n", "\n", "# Function to securely get and set environment variables\n", @@ -122,6 +122,7 @@ "# Step 1: Data Loading\n", "import pandas as pd\n", "from datasets import load_dataset\n", + "\n", "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n", "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n", "\n", @@ -961,9 +962,9 @@ " if isinstance(value, (pd.Series, np.ndarray, list)):\n", " # Handle array-like objects\n", " if len(value) > 0 and not pd.isna(value).all():\n", - " combined.append(f\"{attr.capitalize()}: {str(value)}\")\n", + " combined.append(f\"{attr.capitalize()}: {value!s}\")\n", " elif not pd.isna(value):\n", - " combined.append(f\"{attr.capitalize()}: {str(value)}\")\n", + " combined.append(f\"{attr.capitalize()}: {value!s}\")\n", " return \" \".join(combined)\n", "\n", " df[\"combined_info\"] = df.apply(combine_row, axis=1)\n", @@ -1056,8 +1057,8 @@ "outputs": [], "source": [ "import tiktoken\n", - "from tqdm import tqdm\n", "from langchain_openai import OpenAIEmbeddings\n", + "from tqdm import tqdm\n", "\n", "MAX_TOKENS = 8191 # Maximum tokens for text-embedding-3-small\n", "OVERLAP = 50\n", @@ -1116,14 +1117,13 @@ " if isinstance(input_data, str):\n", " # Return list of embeddings for string input\n", " return chunk_embeddings[0]\n", - " else:\n", - " # Create duplicated rows for each chunk with the respective embedding for row input\n", - " duplicated_rows = []\n", - " for embedding in chunk_embeddings:\n", - " new_row = input_data.copy()\n", - " new_row[\"embedding\"] = embedding\n", - " duplicated_rows.append(new_row)\n", - " return duplicated_rows" + " # Create duplicated rows for each chunk with the respective embedding for row input\n", + " duplicated_rows = []\n", + " for embedding in chunk_embeddings:\n", + " new_row = input_data.copy()\n", + " new_row[\"embedding\"] = embedding\n", + " duplicated_rows.append(new_row)\n", + " return duplicated_rows" ] }, { @@ -2029,8 +2029,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -2059,7 +2058,6 @@ "outputs": [], "source": [ "# Programmatically create vector search index for both colelctions\n", - "import time\n", "from pymongo.operations import SearchIndexModel\n", "\n", "\n", @@ -2086,7 +2084,7 @@ " # time.sleep(20) # Sleep for 20 seconds\n", " print(f\"New index '{index_name}' created successfully:\", result)\n", " except Exception as e:\n", - " print(f\"Error creating new vector search index '{index_name}': {str(e)}\")" + " print(f\"Error creating new vector search index '{index_name}': {e!s}\")" ] }, { @@ -2193,7 +2191,6 @@ "outputs": [], "source": [ "import pandas as pd\n", - "from pymongo import MongoClient\n", "from pymongo.errors import BulkWriteError\n", "\n", "\n", @@ -2506,7 +2503,6 @@ "outputs": [], "source": [ "# Programatically create search indexes\n", - "from pymongo.operations import IndexModel\n", "\n", "\n", "def create_collection_search_index(collection, index_definition, index_name):\n", @@ -2531,7 +2527,7 @@ " print(f\"Search index '{index_name}' created successfully\")\n", " return result\n", " except Exception as e:\n", - " print(f\"Error creating search index: {str(e)}\")\n", + " print(f\"Error creating search index: {e!s}\")\n", " return None\n", "\n", "\n", @@ -2642,9 +2638,9 @@ }, "outputs": [], "source": [ - "from langchain_openai import OpenAIEmbeddings\n", "from langchain_mongodb import MongoDBAtlasVectorSearch\n", "from langchain_mongodb.retrievers import MongoDBAtlasHybridSearchRetriever\n", + "from langchain_openai import OpenAIEmbeddings\n", "\n", "ATLAS_VECTOR_SEARCH_INDEX = \"vector_index_with_filter\"\n", "embedding_model = OpenAIEmbeddings(\n", @@ -2803,12 +2799,11 @@ "source": [ "import pickle\n", "from contextlib import AbstractContextManager\n", + "from datetime import datetime, timezone\n", "from types import TracebackType\n", - "from typing import Any, Dict, Optional, AsyncIterator, Union, List, Tuple\n", + "from typing import Any, AsyncIterator, Dict, List, Optional, Tuple, Union\n", "\n", "from langchain_core.runnables import RunnableConfig\n", - "from typing_extensions import Self\n", - "\n", "from langgraph.checkpoint.base import (\n", " BaseCheckpointSaver,\n", " Checkpoint,\n", @@ -2818,7 +2813,7 @@ ")\n", "from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer\n", "from motor.motor_asyncio import AsyncIOMotorClient\n", - "from datetime import datetime, timezone\n", + "from typing_extensions import Self\n", "\n", "\n", "class JsonPlusSerializerCompat(JsonPlusSerializer):\n", @@ -3015,7 +3010,8 @@ }, "outputs": [], "source": [ - "from typing import Dict, Any\n", + "from typing import Any, Dict\n", + "\n", "from langchain.agents import tool\n", "\n", "\n", @@ -3099,9 +3095,9 @@ }, "outputs": [], "source": [ - "from pydantic import BaseModel, Field, constr\n", "from typing import List\n", - "from datetime import datetime\n", + "\n", + "from pydantic import BaseModel, Field\n", "\n", "\n", "class Step(BaseModel):\n", @@ -3144,7 +3140,7 @@ "\n", " return document\n", " except Exception as e:\n", - " raise ValueError(f\"Invalid safety procedure data: {str(e)}\")\n", + " raise ValueError(f\"Invalid safety procedure data: {e!s}\")\n", "\n", "\n", "# Tool to add new safety procedures\n", @@ -3323,9 +3319,7 @@ }, "outputs": [], "source": [ - "from langchain_openai import ChatOpenAI\n", "from langchain_anthropic import ChatAnthropic\n", - "from langchain_groq import ChatGroq\n", "\n", "# llm = ChatOpenAI(model=\"gpt-4o\", temperature=0)\n", "llm = ChatAnthropic(model=\"claude-3-sonnet-20240229\", temperature=0)\n", @@ -3356,9 +3350,10 @@ }, "outputs": [], "source": [ - "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", "from datetime import datetime\n", "\n", + "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", + "\n", "\n", "def create_agent(llm, tools, system_message: str):\n", " \"\"\"Create an agent.\"\"\"\n", @@ -3512,9 +3507,10 @@ "outputs": [], "source": [ "import operator\n", - "from langchain_core.messages import BaseMessage\n", "from typing import Annotated, TypedDict\n", "\n", + "from langchain_core.messages import BaseMessage\n", + "\n", "\n", "class AgentState(TypedDict):\n", " messages: Annotated[List[BaseMessage], operator.add]\n", @@ -3539,6 +3535,7 @@ "outputs": [], "source": [ "import functools\n", + "\n", "from langchain_core.messages import AIMessage, ToolMessage\n", "\n", "\n", @@ -3676,8 +3673,8 @@ "outputs": [], "source": [ "import asyncio\n", - "from langchain_core.messages import HumanMessage, AIMessage\n", - "import time\n", + "\n", + "from langchain_core.messages import HumanMessage\n", "\n", "\n", "async def chat_loop():\n", @@ -3704,7 +3701,7 @@ " for attempt in range(max_retries):\n", " try:\n", " async for chunk in graph.astream(state, config, stream_mode=\"values\"):\n", - " if \"messages\" in chunk and chunk[\"messages\"]:\n", + " if chunk.get(\"messages\"):\n", " last_message = chunk[\"messages\"][-1]\n", " if isinstance(last_message, AIMessage):\n", " last_message.name = (\n", @@ -3719,12 +3716,12 @@ " break\n", " except Exception as e:\n", " if attempt < max_retries - 1:\n", - " print(f\"\\nAn unexpected error occurred: {str(e)}\")\n", + " print(f\"\\nAn unexpected error occurred: {e!s}\")\n", " print(f\"\\nRetrying in {retry_delay} seconds...\")\n", " await asyncio.sleep(retry_delay)\n", " retry_delay *= 2\n", " else:\n", - " print(f\"\\nMax retries reached. OpenAI API error: {str(e)}\")\n", + " print(f\"\\nMax retries reached. OpenAI API error: {e!s}\")\n", " break\n", "\n", " print(\"\\n\") # New line after the complete response" diff --git a/notebooks/agents/airbnb_agent_openai_llamaindex_mongodb.ipynb b/notebooks/agents/airbnb_agent_openai_llamaindex_mongodb.ipynb index 37191bb..9771a8e 100644 --- a/notebooks/agents/airbnb_agent_openai_llamaindex_mongodb.ipynb +++ b/notebooks/agents/airbnb_agent_openai_llamaindex_mongodb.ipynb @@ -1,1890 +1,1889 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "axgaosQDxyM4" - }, - "source": [ - "# How To Build An AI Agent With OpenAI, LlamaIndex and MongoDB" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "ECTvK2pW84vN" - }, - "source": [ - "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/mongodb-developer/GenAI-Showcase/blob/main/notebooks/agents/airbnb_agent_openai_llamaindex_mongodb.ipynb)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "l7PuZzJDwAWr" - }, - "source": [ - "## Install Libraries" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "jwCBOcXw_nBh", - "outputId": "bb9e4031-5d5c-4b4a-98e3-ff729f6086c7" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/1.6 MB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[91m╸\u001b[0m \u001b[32m1.6/1.6 MB\u001b[0m \u001b[31m51.8 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.6/1.6 MB\u001b[0m \u001b[31m28.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.2/1.2 MB\u001b[0m \u001b[31m32.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.5/1.5 MB\u001b[0m \u001b[31m36.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m176.8/176.8 kB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m295.8/295.8 kB\u001b[0m \u001b[31m12.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.2/1.2 MB\u001b[0m \u001b[31m38.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.5/49.5 kB\u001b[0m \u001b[31m2.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.4/1.4 MB\u001b[0m \u001b[31m21.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m313.6/313.6 kB\u001b[0m \u001b[31m12.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m89.9/89.9 kB\u001b[0m \u001b[31m3.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.1/13.1 MB\u001b[0m \u001b[31m67.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m480.6/480.6 kB\u001b[0m \u001b[31m24.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m116.3/116.3 kB\u001b[0m \u001b[31m6.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m179.3/179.3 kB\u001b[0m \u001b[31m10.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m134.8/134.8 kB\u001b[0m \u001b[31m8.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m194.1/194.1 kB\u001b[0m \u001b[31m11.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25h\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", - "cudf-cu12 24.10.1 requires pandas<2.2.3dev0,>=2.0, but you have pandas 2.2.3 which is incompatible.\n", - "gcsfs 2024.10.0 requires fsspec==2024.10.0, but you have fsspec 2024.9.0 which is incompatible.\n", - "google-colab 1.0.0 requires pandas==2.2.2, but you have pandas 2.2.3 which is incompatible.\u001b[0m\u001b[31m\n", - "\u001b[0m" - ] - } - ], - "source": [ - "!pip install -qU llama-index # main llamaindex libary\n", - "!pip install -qU llama-index-vector-stores-mongodb # mongodb vector database\n", - "!pip install -qU llama-index-llms-openai # openai llm provider\n", - "!pip install -qU llama-index-embeddings-openai # openai embedding provider\n", - "!pip install -qU pymongo pandas datasets # others" - ] + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "axgaosQDxyM4" + }, + "source": [ + "# How To Build An AI Agent With OpenAI, LlamaIndex and MongoDB" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ECTvK2pW84vN" + }, + "source": [ + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/mongodb-developer/GenAI-Showcase/blob/main/notebooks/agents/airbnb_agent_openai_llamaindex_mongodb.ipynb)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "l7PuZzJDwAWr" + }, + "source": [ + "## Install Libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" }, + "id": "jwCBOcXw_nBh", + "outputId": "bb9e4031-5d5c-4b4a-98e3-ff729f6086c7" + }, + "outputs": [ { - "cell_type": "markdown", - "metadata": { - "id": "siDlNHlKwGgE" - }, - "source": [ - "## Setup Prerequisites" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/1.6 MB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[91m╸\u001b[0m \u001b[32m1.6/1.6 MB\u001b[0m \u001b[31m51.8 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.6/1.6 MB\u001b[0m \u001b[31m28.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.2/1.2 MB\u001b[0m \u001b[31m32.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.5/1.5 MB\u001b[0m \u001b[31m36.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m176.8/176.8 kB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m295.8/295.8 kB\u001b[0m \u001b[31m12.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.2/1.2 MB\u001b[0m \u001b[31m38.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.5/49.5 kB\u001b[0m \u001b[31m2.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.4/1.4 MB\u001b[0m \u001b[31m21.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m313.6/313.6 kB\u001b[0m \u001b[31m12.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m89.9/89.9 kB\u001b[0m \u001b[31m3.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.1/13.1 MB\u001b[0m \u001b[31m67.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m480.6/480.6 kB\u001b[0m \u001b[31m24.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m116.3/116.3 kB\u001b[0m \u001b[31m6.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m179.3/179.3 kB\u001b[0m \u001b[31m10.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m134.8/134.8 kB\u001b[0m \u001b[31m8.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m194.1/194.1 kB\u001b[0m \u001b[31m11.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25h\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", + "cudf-cu12 24.10.1 requires pandas<2.2.3dev0,>=2.0, but you have pandas 2.2.3 which is incompatible.\n", + "gcsfs 2024.10.0 requires fsspec==2024.10.0, but you have fsspec 2024.9.0 which is incompatible.\n", + "google-colab 1.0.0 requires pandas==2.2.2, but you have pandas 2.2.3 which is incompatible.\u001b[0m\u001b[31m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "!pip install -qU llama-index # main llamaindex libary\n", + "!pip install -qU llama-index-vector-stores-mongodb # mongodb vector database\n", + "!pip install -qU llama-index-llms-openai # openai llm provider\n", + "!pip install -qU llama-index-embeddings-openai # openai embedding provider\n", + "!pip install -qU pymongo pandas datasets # others" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "siDlNHlKwGgE" + }, + "source": [ + "## Setup Prerequisites" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "id": "3v6adnzJ9INt" + }, + "outputs": [], + "source": [ + "import getpass\n", + "import os\n", + "\n", + "from pymongo import MongoClient" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" }, + "id": "2sxMs_60wNPD", + "outputId": "5bf5d12a-8b65-424f-cd7d-b6ac6051e830" + }, + "outputs": [ { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "id": "3v6adnzJ9INt" - }, - "outputs": [], - "source": [ - "import os\n", - "import getpass\n", - "from pymongo import MongoClient" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter OpenAI API Key:··········\n" + ] + } + ], + "source": [ + "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"Enter OpenAI API Key:\")" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" }, + "id": "2cNHYOBGKDTd", + "outputId": "9a206804-d634-4aa6-c1a8-22c1fd842b6d" + }, + "outputs": [ { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "2sxMs_60wNPD", - "outputId": "5bf5d12a-8b65-424f-cd7d-b6ac6051e830" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Enter OpenAI API Key:··········\n" - ] - } - ], - "source": [ - "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"Enter OpenAI API Key:\")" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter your MongoDB URI: ··········\n" + ] + } + ], + "source": [ + "MONGODB_URI = getpass.getpass(\"Enter your MongoDB URI: \")\n", + "mongodb_client = MongoClient(\n", + " MONGODB_URI, appname=\"devrel.content.airbnb_agent_mongodb_llamaindex\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "osmgS5DbxD7h" + }, + "source": [ + "## Configure LLMs and Embedding Models" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "id": "qz0tqiaswbKW" + }, + "outputs": [], + "source": [ + "from llama_index.core import Settings\n", + "from llama_index.embeddings.openai import OpenAIEmbedding\n", + "from llama_index.llms.openai import OpenAI\n", + "\n", + "Settings.embed_model = OpenAIEmbedding(\n", + " model=\"text-embedding-3-small\",\n", + " dimensions=256,\n", + " embed_batch_size=10,\n", + " openai_api_key=os.environ[\"OPENAI_API_KEY\"],\n", + ")\n", + "llm = OpenAI(model=\"gpt-4o\", temperature=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "OwX4bbG2xeHG" + }, + "source": [ + "## Download the Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "id": "1MWkFKGy__ut" + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "from datasets import load_dataset\n", + "\n", + "# https://huggingface.co/datasets/MongoDB/airbnb_embeddings\n", + "data = load_dataset(\"MongoDB/airbnb_embeddings\", split=\"train\", streaming=True)\n", + "data = data.take(200)\n", + "\n", + "# Convert the dataset to a pandas dataframe\n", + "data_df = pd.DataFrame(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 759 }, + "id": "6VZLQgaHI0VD", + "outputId": "1f86ddd5-e9f6-417f-905b-fbc953a87d15" + }, + "outputs": [ { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "2cNHYOBGKDTd", - "outputId": "9a206804-d634-4aa6-c1a8-22c1fd842b6d" + "data": { + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "data_df" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Enter your MongoDB URI: ··········\n" - ] - } + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
_idlisting_urlnamesummaryspacedescriptionneighborhood_overviewnotestransitaccess...imageshostaddressavailabilityreview_scoresreviewsweekly_pricemonthly_pricetext_embeddingsimage_embeddings
010006546https://www.airbnb.com/rooms/10006546Ribeira Charming DuplexFantastic duplex apartment with three bedrooms...Privileged views of the Douro River and Ribeir...Fantastic duplex apartment with three bedrooms...In the neighborhood of the river, you can find...Lose yourself in the narrow streets and stairc...Transport: • Metro station and S. Bento railwa...We are always available to help guests. The ho......{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '51399391', 'host_url': 'https://w...{'street': 'Porto, Porto, Portugal', 'suburb':...{'availability_30': 28, 'availability_60': 47,...{'review_scores_accuracy': 9, 'review_scores_c...[{'_id': '58663741', 'date': 2016-01-03 05:00:...NaNNaN[0.0123710884, -0.0180913936, -0.016843712, -0...[-0.1302358955, 0.1534578055, 0.0199299306, -0...
110021707https://www.airbnb.com/rooms/10021707Private Room in BushwickHere exists a very cozy room for rent in a sha...Here exists a very cozy room for rent in a sha......{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '11275734', 'host_url': 'https://w...{'street': 'Brooklyn, NY, United States', 'sub...{'availability_30': 0, 'availability_60': 0, '...{'review_scores_accuracy': 10, 'review_scores_...[{'_id': '61050713', 'date': 2016-01-31 05:00:...NaNNaN[0.0153845912, -0.0348115042, -0.0093448907, 0...[0.0340401195, 0.1742489338, -0.1572628617, 0....
21001265https://www.airbnb.com/rooms/1001265Ocean View Waikiki Marina w/prkgA short distance from Honolulu's billion dolla...Great studio located on Ala Moana across the s...A short distance from Honolulu's billion dolla...You can breath ocean as well as aloha.Honolulu does have a very good air conditioned...Pool, hot tub and tennis...{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '5448114', 'host_url': 'https://ww...{'street': 'Honolulu, HI, United States', 'sub...{'availability_30': 16, 'availability_60': 46,...{'review_scores_accuracy': 9, 'review_scores_c...[{'_id': '4765259', 'date': 2013-05-24 04:00:0...650.02150.0[-0.0400562622, -0.0405789167, 0.000644172, 0....[-0.1640156209, 0.1256971657, 0.6594450474, -0...
310009999https://www.airbnb.com/rooms/10009999Horto flat with small gardenOne bedroom + sofa-bed in quiet and bucolic ne...Lovely one bedroom + sofa-bed in the living ro...One bedroom + sofa-bed in quiet and bucolic ne...This charming ground floor flat is located in ...There´s a table in the living room now, that d...Easy access to transport (bus, taxi, car) and ......{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '1282196', 'host_url': 'https://ww...{'street': 'Rio de Janeiro, Rio de Janeiro, Br...{'availability_30': 0, 'availability_60': 0, '...{'review_scores_accuracy': None, 'review_score...[]1492.04849.0[-0.063234821, 0.0017937823, -0.0243996996, -0...[-0.1292964518, 0.037789464, 0.2443587631, 0.0...
410047964https://www.airbnb.com/rooms/10047964Charming Flat in Downtown ModaFully furnished 3+1 flat decorated with vintag...The apartment is composed of 1 big bedroom wit...Fully furnished 3+1 flat decorated with vintag...With its diversity Moda- Kadikoy is one of the......{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '1241644', 'host_url': 'https://ww...{'street': 'Kadıköy, İstanbul, Turkey', 'subur...{'availability_30': 27, 'availability_60': 57,...{'review_scores_accuracy': 10, 'review_scores_...[{'_id': '68162172', 'date': 2016-04-02 04:00:...NaNNaN[0.023723349, 0.0064210771, -0.0339970738, -0....[-0.1006749049, 0.4022984803, -0.1821258366, 0...
\n", + "

5 rows × 43 columns

\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
\n", + "\n", + "
\n", + "
\n" ], - "source": [ - "MONGODB_URI = getpass.getpass(\"Enter your MongoDB URI: \")\n", - "mongodb_client = MongoClient(\n", - " MONGODB_URI, appname=\"devrel.content.airbnb_agent_mongodb_llamaindex\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "osmgS5DbxD7h" - }, - "source": [ - "## Configure LLMs and Embedding Models" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": { - "id": "qz0tqiaswbKW" - }, - "outputs": [], - "source": [ - "from llama_index.embeddings.openai import OpenAIEmbedding\n", - "from llama_index.llms.openai import OpenAI\n", - "from llama_index.core import Settings\n", - "\n", - "Settings.embed_model = OpenAIEmbedding(\n", - " model=\"text-embedding-3-small\",\n", - " dimensions=256,\n", - " embed_batch_size=10,\n", - " openai_api_key=os.environ[\"OPENAI_API_KEY\"],\n", - ")\n", - "llm = OpenAI(model=\"gpt-4o\", temperature=0)" + "text/plain": [ + " _id listing_url \\\n", + "0 10006546 https://www.airbnb.com/rooms/10006546 \n", + "1 10021707 https://www.airbnb.com/rooms/10021707 \n", + "2 1001265 https://www.airbnb.com/rooms/1001265 \n", + "3 10009999 https://www.airbnb.com/rooms/10009999 \n", + "4 10047964 https://www.airbnb.com/rooms/10047964 \n", + "\n", + " name \\\n", + "0 Ribeira Charming Duplex \n", + "1 Private Room in Bushwick \n", + "2 Ocean View Waikiki Marina w/prkg \n", + "3 Horto flat with small garden \n", + "4 Charming Flat in Downtown Moda \n", + "\n", + " summary \\\n", + "0 Fantastic duplex apartment with three bedrooms... \n", + "1 Here exists a very cozy room for rent in a sha... \n", + "2 A short distance from Honolulu's billion dolla... \n", + "3 One bedroom + sofa-bed in quiet and bucolic ne... \n", + "4 Fully furnished 3+1 flat decorated with vintag... \n", + "\n", + " space \\\n", + "0 Privileged views of the Douro River and Ribeir... \n", + "1 \n", + "2 Great studio located on Ala Moana across the s... \n", + "3 Lovely one bedroom + sofa-bed in the living ro... \n", + "4 The apartment is composed of 1 big bedroom wit... \n", + "\n", + " description \\\n", + "0 Fantastic duplex apartment with three bedrooms... \n", + "1 Here exists a very cozy room for rent in a sha... \n", + "2 A short distance from Honolulu's billion dolla... \n", + "3 One bedroom + sofa-bed in quiet and bucolic ne... \n", + "4 Fully furnished 3+1 flat decorated with vintag... \n", + "\n", + " neighborhood_overview \\\n", + "0 In the neighborhood of the river, you can find... \n", + "1 \n", + "2 You can breath ocean as well as aloha. \n", + "3 This charming ground floor flat is located in ... \n", + "4 With its diversity Moda- Kadikoy is one of the... \n", + "\n", + " notes \\\n", + "0 Lose yourself in the narrow streets and stairc... \n", + "1 \n", + "2 \n", + "3 There´s a table in the living room now, that d... \n", + "4 \n", + "\n", + " transit \\\n", + "0 Transport: • Metro station and S. Bento railwa... \n", + "1 \n", + "2 Honolulu does have a very good air conditioned... \n", + "3 Easy access to transport (bus, taxi, car) and ... \n", + "4 \n", + "\n", + " access ... \\\n", + "0 We are always available to help guests. The ho... ... \n", + "1 ... \n", + "2 Pool, hot tub and tennis ... \n", + "3 ... \n", + "4 ... \n", + "\n", + " images \\\n", + "0 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", + "1 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", + "2 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", + "3 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", + "4 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", + "\n", + " host \\\n", + "0 {'host_id': '51399391', 'host_url': 'https://w... \n", + "1 {'host_id': '11275734', 'host_url': 'https://w... \n", + "2 {'host_id': '5448114', 'host_url': 'https://ww... \n", + "3 {'host_id': '1282196', 'host_url': 'https://ww... \n", + "4 {'host_id': '1241644', 'host_url': 'https://ww... \n", + "\n", + " address \\\n", + "0 {'street': 'Porto, Porto, Portugal', 'suburb':... \n", + "1 {'street': 'Brooklyn, NY, United States', 'sub... \n", + "2 {'street': 'Honolulu, HI, United States', 'sub... \n", + "3 {'street': 'Rio de Janeiro, Rio de Janeiro, Br... \n", + "4 {'street': 'Kadıköy, İstanbul, Turkey', 'subur... \n", + "\n", + " availability \\\n", + "0 {'availability_30': 28, 'availability_60': 47,... \n", + "1 {'availability_30': 0, 'availability_60': 0, '... \n", + "2 {'availability_30': 16, 'availability_60': 46,... \n", + "3 {'availability_30': 0, 'availability_60': 0, '... \n", + "4 {'availability_30': 27, 'availability_60': 57,... \n", + "\n", + " review_scores \\\n", + "0 {'review_scores_accuracy': 9, 'review_scores_c... \n", + "1 {'review_scores_accuracy': 10, 'review_scores_... \n", + "2 {'review_scores_accuracy': 9, 'review_scores_c... \n", + "3 {'review_scores_accuracy': None, 'review_score... \n", + "4 {'review_scores_accuracy': 10, 'review_scores_... \n", + "\n", + " reviews weekly_price \\\n", + "0 [{'_id': '58663741', 'date': 2016-01-03 05:00:... NaN \n", + "1 [{'_id': '61050713', 'date': 2016-01-31 05:00:... NaN \n", + "2 [{'_id': '4765259', 'date': 2013-05-24 04:00:0... 650.0 \n", + "3 [] 1492.0 \n", + "4 [{'_id': '68162172', 'date': 2016-04-02 04:00:... NaN \n", + "\n", + " monthly_price text_embeddings \\\n", + "0 NaN [0.0123710884, -0.0180913936, -0.016843712, -0... \n", + "1 NaN [0.0153845912, -0.0348115042, -0.0093448907, 0... \n", + "2 2150.0 [-0.0400562622, -0.0405789167, 0.000644172, 0.... \n", + "3 4849.0 [-0.063234821, 0.0017937823, -0.0243996996, -0... \n", + "4 NaN [0.023723349, 0.0064210771, -0.0339970738, -0.... \n", + "\n", + " image_embeddings \n", + "0 [-0.1302358955, 0.1534578055, 0.0199299306, -0... \n", + "1 [0.0340401195, 0.1742489338, -0.1572628617, 0.... \n", + "2 [-0.1640156209, 0.1256971657, 0.6594450474, -0... \n", + "3 [-0.1292964518, 0.037789464, 0.2443587631, 0.0... \n", + "4 [-0.1006749049, 0.4022984803, -0.1821258366, 0... \n", + "\n", + "[5 rows x 43 columns]" ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data_df.head(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "tlMnDPOfzMK5" + }, + "source": [ + "## Data Processing" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "id": "iu3PppUWJjMc" + }, + "outputs": [], + "source": [ + "from llama_index.core import Document" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "id": "4zCDxG4_IiiK" + }, + "outputs": [], + "source": [ + "# Convert the DataFrame to dictionary\n", + "docs = data_df.to_dict(orient=\"records\")" + ] + }, + { + "cell_type": "code", + "execution_count": 167, + "metadata": { + "id": "uyl1ChTXIk9h" + }, + "outputs": [], + "source": [ + "llama_documents = []\n", + "fields_to_include = [\n", + " \"amenities\",\n", + " \"address\",\n", + " \"availability\",\n", + " \"review_scores\",\n", + " \"listing_url\",\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 168, + "metadata": { + "id": "AWpooso1Amft" + }, + "outputs": [], + "source": [ + "for doc in docs:\n", + " metadata = {key: doc[key] for key in fields_to_include}\n", + " llama_doc = Document(text=doc[\"description\"], metadata=metadata)\n", + " llama_documents.append(llama_doc)" + ] + }, + { + "cell_type": "code", + "execution_count": 169, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" }, + "id": "dIeOtRRuJXKi", + "outputId": "3f8395c6-3cb5-4486-d9f3-c8aa062ea47f" + }, + "outputs": [ { - "cell_type": "markdown", - "metadata": { - "id": "OwX4bbG2xeHG" - }, - "source": [ - "## Download the Dataset" + "data": { + "text/plain": [ + "Document(id_='54f8e3ba-9624-4ac4-986a-e19d67a89e7c', embedding=None, metadata={'amenities': ['TV', 'Cable TV', 'Wifi', 'Kitchen', 'Paid parking off premises', 'Smoking allowed', 'Pets allowed', 'Buzzer/wireless intercom', 'Heating', 'Family/kid friendly', 'Washer', 'First aid kit', 'Fire extinguisher', 'Essentials', 'Hangers', 'Hair dryer', 'Iron', 'Pack ’n Play/travel crib', 'Room-darkening shades', 'Hot water', 'Bed linens', 'Extra pillows and blankets', 'Microwave', 'Coffee maker', 'Refrigerator', 'Dishwasher', 'Dishes and silverware', 'Cooking basics', 'Oven', 'Stove', 'Cleaning before checkout', 'Waterfront'], 'address': {'street': 'Porto, Porto, Portugal', 'suburb': '', 'government_area': 'Cedofeita, Ildefonso, Sé, Miragaia, Nicolau, Vitória', 'market': 'Porto', 'country': 'Portugal', 'country_code': 'PT', 'location': {'type': 'Point', 'coordinates': [-8.61308, 41.1413], 'is_location_exact': False}}, 'availability': {'availability_30': 28, 'availability_60': 47, 'availability_90': 74, 'availability_365': 239}, 'review_scores': {'review_scores_accuracy': 9, 'review_scores_cleanliness': 9, 'review_scores_checkin': 10, 'review_scores_communication': 10, 'review_scores_location': 10, 'review_scores_value': 9, 'review_scores_rating': 89}, 'listing_url': 'https://www.airbnb.com/rooms/10006546'}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, text='Fantastic duplex apartment with three bedrooms, located in the historic area of Porto, Ribeira (Cube) - UNESCO World Heritage Site. Centenary building fully rehabilitated, without losing their original character. Privileged views of the Douro River and Ribeira square, our apartment offers the perfect conditions to discover the history and the charm of Porto. Apartment comfortable, charming, romantic and cozy in the heart of Ribeira. Within walking distance of all the most emblematic places of the city of Porto. The apartment is fully equipped to host 8 people, with cooker, oven, washing machine, dishwasher, microwave, coffee machine (Nespresso) and kettle. The apartment is located in a very typical area of the city that allows to cross with the most picturesque population of the city, welcoming, genuine and happy people that fills the streets with his outspoken speech and contagious with your sincere generosity, wrapped in a only parochial spirit. We are always available to help guests', mimetype='text/plain', start_char_idx=None, end_char_idx=None, text_template='{metadata_str}\\n\\n{content}', metadata_template='{key}: {value}', metadata_seperator='\\n')" ] + }, + "execution_count": 169, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "llama_documents[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dC7CDZGhzPLn" + }, + "source": [ + "## Create MongoDB Atlas Vector Store" + ] + }, + { + "cell_type": "code", + "execution_count": 186, + "metadata": { + "id": "HCVyW9xGKrF3" + }, + "outputs": [], + "source": [ + "from llama_index.core import StorageContext, VectorStoreIndex\n", + "from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch\n", + "from pymongo.errors import OperationFailure" + ] + }, + { + "cell_type": "code", + "execution_count": 187, + "metadata": { + "id": "iCqflLPNBZe4" + }, + "outputs": [], + "source": [ + "DB_NAME = \"airbnb\"\n", + "COLLECTION_NAME = \"listings_reviews\"\n", + "VS_INDEX_NAME = \"vector_index\"\n", + "FTS_INDEX_NAME = \"fts_index\"\n", + "collection = mongodb_client[DB_NAME][COLLECTION_NAME]" + ] + }, + { + "cell_type": "code", + "execution_count": 189, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 81, + "referenced_widgets": [ + "435f2a6981e64882b94cbe137eadddde", + "fce1edc87223443bb9dce94d9cd930bc", + "9ffc973f8c8844c59c1c999746bc87b9", + "225f2955a7314e949f4d1fc90e0fdcb8", + "f4a60ad3051942e7b1c68a8364c300e7", + "75ca100699444d04ae5c03d027473886", + "cfae9079f4e64e7a8798619a3aa9b4cc", + "b5e34cde4278413d977193885a74149c", + "786458928ada491eb2c9468f422b85fb", + "2add43683c5b4dfab0b7224bb0a4b71c", + "f61a6afef1d646afa11d57b57e7d573a", + "6f0165eb239e4c11bd7aff65f79b1a6b", + "975f53abc78e49088fba9a825663d91f", + "bc7980ba565f42d4bfdeeae6bf427daa", + "d101bd0c5ddd44ee91e94cb2c6df33a8", + "96e691ddb8b1472d850fe09b862101bb", + "3a4035af32374d9f8163bd19d13504fa", + "406fbc51c11344998647f5ee66901fc4", + "e0c0df23ca744bc6a123bb31b6c17915", + "d3eacb1dd8cf4d5aa85592c5806a5821", + "9a9ba8090fb74458848eeb0ea7ecea17", + "53be48022b114167ae066632ccfdd480" + ] }, + "id": "D5sne8YMBa80", + "outputId": "38fa666c-99ed-4ff0-8f10-c7f94da8c48d" + }, + "outputs": [ { - "cell_type": "code", - "execution_count": 29, - "metadata": { - "id": "1MWkFKGy__ut" + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "435f2a6981e64882b94cbe137eadddde", + "version_major": 2, + "version_minor": 0 }, - "outputs": [], - "source": [ - "from datasets import load_dataset\n", - "import pandas as pd\n", - "\n", - "# https://huggingface.co/datasets/MongoDB/airbnb_embeddings\n", - "data = load_dataset(\"MongoDB/airbnb_embeddings\", split=\"train\", streaming=True)\n", - "data = data.take(200)\n", - "\n", - "# Convert the dataset to a pandas dataframe\n", - "data_df = pd.DataFrame(data)" + "text/plain": [ + "Parsing nodes: 0%| | 0/200 [00:00\n", - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
_idlisting_urlnamesummaryspacedescriptionneighborhood_overviewnotestransitaccess...imageshostaddressavailabilityreview_scoresreviewsweekly_pricemonthly_pricetext_embeddingsimage_embeddings
010006546https://www.airbnb.com/rooms/10006546Ribeira Charming DuplexFantastic duplex apartment with three bedrooms...Privileged views of the Douro River and Ribeir...Fantastic duplex apartment with three bedrooms...In the neighborhood of the river, you can find...Lose yourself in the narrow streets and stairc...Transport: • Metro station and S. Bento railwa...We are always available to help guests. The ho......{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '51399391', 'host_url': 'https://w...{'street': 'Porto, Porto, Portugal', 'suburb':...{'availability_30': 28, 'availability_60': 47,...{'review_scores_accuracy': 9, 'review_scores_c...[{'_id': '58663741', 'date': 2016-01-03 05:00:...NaNNaN[0.0123710884, -0.0180913936, -0.016843712, -0...[-0.1302358955, 0.1534578055, 0.0199299306, -0...
110021707https://www.airbnb.com/rooms/10021707Private Room in BushwickHere exists a very cozy room for rent in a sha...Here exists a very cozy room for rent in a sha......{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '11275734', 'host_url': 'https://w...{'street': 'Brooklyn, NY, United States', 'sub...{'availability_30': 0, 'availability_60': 0, '...{'review_scores_accuracy': 10, 'review_scores_...[{'_id': '61050713', 'date': 2016-01-31 05:00:...NaNNaN[0.0153845912, -0.0348115042, -0.0093448907, 0...[0.0340401195, 0.1742489338, -0.1572628617, 0....
21001265https://www.airbnb.com/rooms/1001265Ocean View Waikiki Marina w/prkgA short distance from Honolulu's billion dolla...Great studio located on Ala Moana across the s...A short distance from Honolulu's billion dolla...You can breath ocean as well as aloha.Honolulu does have a very good air conditioned...Pool, hot tub and tennis...{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '5448114', 'host_url': 'https://ww...{'street': 'Honolulu, HI, United States', 'sub...{'availability_30': 16, 'availability_60': 46,...{'review_scores_accuracy': 9, 'review_scores_c...[{'_id': '4765259', 'date': 2013-05-24 04:00:0...650.02150.0[-0.0400562622, -0.0405789167, 0.000644172, 0....[-0.1640156209, 0.1256971657, 0.6594450474, -0...
310009999https://www.airbnb.com/rooms/10009999Horto flat with small gardenOne bedroom + sofa-bed in quiet and bucolic ne...Lovely one bedroom + sofa-bed in the living ro...One bedroom + sofa-bed in quiet and bucolic ne...This charming ground floor flat is located in ...There´s a table in the living room now, that d...Easy access to transport (bus, taxi, car) and ......{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '1282196', 'host_url': 'https://ww...{'street': 'Rio de Janeiro, Rio de Janeiro, Br...{'availability_30': 0, 'availability_60': 0, '...{'review_scores_accuracy': None, 'review_score...[]1492.04849.0[-0.063234821, 0.0017937823, -0.0243996996, -0...[-0.1292964518, 0.037789464, 0.2443587631, 0.0...
410047964https://www.airbnb.com/rooms/10047964Charming Flat in Downtown ModaFully furnished 3+1 flat decorated with vintag...The apartment is composed of 1 big bedroom wit...Fully furnished 3+1 flat decorated with vintag...With its diversity Moda- Kadikoy is one of the......{'thumbnail_url': '', 'medium_url': '', 'pictu...{'host_id': '1241644', 'host_url': 'https://ww...{'street': 'Kadıköy, İstanbul, Turkey', 'subur...{'availability_30': 27, 'availability_60': 57,...{'review_scores_accuracy': 10, 'review_scores_...[{'_id': '68162172', 'date': 2016-04-02 04:00:...NaNNaN[0.023723349, 0.0064210771, -0.0339970738, -0....[-0.1006749049, 0.4022984803, -0.1821258366, 0...
\n", - "

5 rows × 43 columns

\n", - "
\n", - "
\n", - "\n", - "
\n", - " \n", - "\n", - " \n", - "\n", - " \n", - "
\n", - "\n", - "\n", - "
\n", - " \n", - "\n", - "\n", - "\n", - " \n", - "
\n", - "\n", - "
\n", - " \n" - ], - "text/plain": [ - " _id listing_url \\\n", - "0 10006546 https://www.airbnb.com/rooms/10006546 \n", - "1 10021707 https://www.airbnb.com/rooms/10021707 \n", - "2 1001265 https://www.airbnb.com/rooms/1001265 \n", - "3 10009999 https://www.airbnb.com/rooms/10009999 \n", - "4 10047964 https://www.airbnb.com/rooms/10047964 \n", - "\n", - " name \\\n", - "0 Ribeira Charming Duplex \n", - "1 Private Room in Bushwick \n", - "2 Ocean View Waikiki Marina w/prkg \n", - "3 Horto flat with small garden \n", - "4 Charming Flat in Downtown Moda \n", - "\n", - " summary \\\n", - "0 Fantastic duplex apartment with three bedrooms... \n", - "1 Here exists a very cozy room for rent in a sha... \n", - "2 A short distance from Honolulu's billion dolla... \n", - "3 One bedroom + sofa-bed in quiet and bucolic ne... \n", - "4 Fully furnished 3+1 flat decorated with vintag... \n", - "\n", - " space \\\n", - "0 Privileged views of the Douro River and Ribeir... \n", - "1 \n", - "2 Great studio located on Ala Moana across the s... \n", - "3 Lovely one bedroom + sofa-bed in the living ro... \n", - "4 The apartment is composed of 1 big bedroom wit... \n", - "\n", - " description \\\n", - "0 Fantastic duplex apartment with three bedrooms... \n", - "1 Here exists a very cozy room for rent in a sha... \n", - "2 A short distance from Honolulu's billion dolla... \n", - "3 One bedroom + sofa-bed in quiet and bucolic ne... \n", - "4 Fully furnished 3+1 flat decorated with vintag... \n", - "\n", - " neighborhood_overview \\\n", - "0 In the neighborhood of the river, you can find... \n", - "1 \n", - "2 You can breath ocean as well as aloha. \n", - "3 This charming ground floor flat is located in ... \n", - "4 With its diversity Moda- Kadikoy is one of the... \n", - "\n", - " notes \\\n", - "0 Lose yourself in the narrow streets and stairc... \n", - "1 \n", - "2 \n", - "3 There´s a table in the living room now, that d... \n", - "4 \n", - "\n", - " transit \\\n", - "0 Transport: • Metro station and S. Bento railwa... \n", - "1 \n", - "2 Honolulu does have a very good air conditioned... \n", - "3 Easy access to transport (bus, taxi, car) and ... \n", - "4 \n", - "\n", - " access ... \\\n", - "0 We are always available to help guests. The ho... ... \n", - "1 ... \n", - "2 Pool, hot tub and tennis ... \n", - "3 ... \n", - "4 ... \n", - "\n", - " images \\\n", - "0 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", - "1 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", - "2 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", - "3 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", - "4 {'thumbnail_url': '', 'medium_url': '', 'pictu... \n", - "\n", - " host \\\n", - "0 {'host_id': '51399391', 'host_url': 'https://w... \n", - "1 {'host_id': '11275734', 'host_url': 'https://w... \n", - "2 {'host_id': '5448114', 'host_url': 'https://ww... \n", - "3 {'host_id': '1282196', 'host_url': 'https://ww... \n", - "4 {'host_id': '1241644', 'host_url': 'https://ww... \n", - "\n", - " address \\\n", - "0 {'street': 'Porto, Porto, Portugal', 'suburb':... \n", - "1 {'street': 'Brooklyn, NY, United States', 'sub... \n", - "2 {'street': 'Honolulu, HI, United States', 'sub... \n", - "3 {'street': 'Rio de Janeiro, Rio de Janeiro, Br... \n", - "4 {'street': 'Kadıköy, İstanbul, Turkey', 'subur... \n", - "\n", - " availability \\\n", - "0 {'availability_30': 28, 'availability_60': 47,... \n", - "1 {'availability_30': 0, 'availability_60': 0, '... \n", - "2 {'availability_30': 16, 'availability_60': 46,... \n", - "3 {'availability_30': 0, 'availability_60': 0, '... \n", - "4 {'availability_30': 27, 'availability_60': 57,... \n", - "\n", - " review_scores \\\n", - "0 {'review_scores_accuracy': 9, 'review_scores_c... \n", - "1 {'review_scores_accuracy': 10, 'review_scores_... \n", - "2 {'review_scores_accuracy': 9, 'review_scores_c... \n", - "3 {'review_scores_accuracy': None, 'review_score... \n", - "4 {'review_scores_accuracy': 10, 'review_scores_... \n", - "\n", - " reviews weekly_price \\\n", - "0 [{'_id': '58663741', 'date': 2016-01-03 05:00:... NaN \n", - "1 [{'_id': '61050713', 'date': 2016-01-31 05:00:... NaN \n", - "2 [{'_id': '4765259', 'date': 2013-05-24 04:00:0... 650.0 \n", - "3 [] 1492.0 \n", - "4 [{'_id': '68162172', 'date': 2016-04-02 04:00:... NaN \n", - "\n", - " monthly_price text_embeddings \\\n", - "0 NaN [0.0123710884, -0.0180913936, -0.016843712, -0... \n", - "1 NaN [0.0153845912, -0.0348115042, -0.0093448907, 0... \n", - "2 2150.0 [-0.0400562622, -0.0405789167, 0.000644172, 0.... \n", - "3 4849.0 [-0.063234821, 0.0017937823, -0.0243996996, -0... \n", - "4 NaN [0.023723349, 0.0064210771, -0.0339970738, -0.... \n", - "\n", - " image_embeddings \n", - "0 [-0.1302358955, 0.1534578055, 0.0199299306, -0... \n", - "1 [0.0340401195, 0.1742489338, -0.1572628617, 0.... \n", - "2 [-0.1640156209, 0.1256971657, 0.6594450474, -0... \n", - "3 [-0.1292964518, 0.037789464, 0.2443587631, 0.0... \n", - "4 [-0.1006749049, 0.4022984803, -0.1821258366, 0... \n", - "\n", - "[5 rows x 43 columns]" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "data_df.head(5)" + "text/plain": [ + "Generating embeddings: 0%| | 0/200 [00:00.\n", + "Successfully created index for model .\n" + ] + } + ], + "source": [ + "for model in [vs_model, fts_model]:\n", + " try:\n", + " collection.create_search_index(model=model)\n", + " print(f\"Successfully created index for model {model}.\")\n", + " except OperationFailure:\n", + " print(f\"Duplicate index found for model {model}. Skipping index creation.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZqjMKHMizlOM" + }, + "source": [ + "## Creating Retriever Tool for the Agent" + ] + }, + { + "cell_type": "code", + "execution_count": 194, + "metadata": { + "id": "tHvIkj-UM72t" + }, + "outputs": [], + "source": [ + "from typing import List\n", + "\n", + "from llama_index.core.tools import FunctionTool\n", + "from llama_index.core.vector_stores import (\n", + " FilterCondition,\n", + " FilterOperator,\n", + " MetadataFilter,\n", + " MetadataFilters,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 195, + "metadata": { + "id": "XVz-iQDFRwnH" + }, + "outputs": [], + "source": [ + "def get_airbnb_listings(query: str, amenities: List[str]) -> str:\n", + " \"\"\"\n", + " Provides information about Airbnb listings.\n", + "\n", + " query (str): User query\n", + " amenities (List[str]): List of amenities\n", + " rating (int): Listing rating\n", + " \"\"\"\n", + " filters = [\n", + " MetadataFilter(\n", + " key=\"metadata.review_scores.review_scores_rating\",\n", + " value=80,\n", + " operator=FilterOperator.GTE,\n", + " )\n", + " ]\n", + " amenities_filter = [\n", + " MetadataFilter(\n", + " key=\"metadata.amenities\", value=amenity, operator=FilterOperator.EQ\n", + " )\n", + " for amenity in amenities\n", + " ]\n", + " filters.extend(amenities_filter)\n", + "\n", + " filters = MetadataFilters(\n", + " filters=filters,\n", + " condition=FilterCondition.AND,\n", + " )\n", + "\n", + " query_engine = vector_store_index.as_query_engine(\n", + " similarity_top_k=5, vector_store_query_mode=\"hybrid\", alpha=0.7, filters=filters\n", + " )\n", + " response = query_engine.query(query)\n", + " nodes = response.source_nodes\n", + " listings = [node.metadata[\"listing_url\"] for node in nodes]\n", + " return listings" + ] + }, + { + "cell_type": "code", + "execution_count": 196, + "metadata": { + "id": "-89_2_OXTuz9" + }, + "outputs": [], + "source": [ + "query_tool = FunctionTool.from_defaults(\n", + " name=\"get_airbnb_listings\", fn=get_airbnb_listings\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GyCMYLAB1ifQ" + }, + "source": [ + "## Create the AI Agent" + ] + }, + { + "cell_type": "code", + "execution_count": 197, + "metadata": { + "id": "13WPPB5RPR1o" + }, + "outputs": [], + "source": [ + "from llama_index.core.agent import AgentRunner, FunctionCallingAgentWorker" + ] + }, + { + "cell_type": "code", + "execution_count": 198, + "metadata": { + "id": "3JKQeSbePU-3" + }, + "outputs": [], + "source": [ + "agent_worker = FunctionCallingAgentWorker.from_tools(\n", + " [query_tool], llm=llm, verbose=True\n", + ")\n", + "agent = AgentRunner(agent_worker)" + ] + }, + { + "cell_type": "code", + "execution_count": 199, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" }, + "id": "f0PVXC07PoCx", + "outputId": "7f4f27bb-5a5c-430e-9004-228482ca4fa8" + }, + "outputs": [ { - "cell_type": "code", - "execution_count": 31, - "metadata": { - "id": "iu3PppUWJjMc" - }, - "outputs": [], - "source": [ - "import json\n", - "from llama_index.core import Document\n", - "from llama_index.core.schema import MetadataMode" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "Added user message to memory: Give me listings in Porto with a Waterfront.\n", + "=== Calling Function ===\n", + "Calling function: get_airbnb_listings with args: {\"query\": \"Porto\", \"amenities\": [\"Waterfront\"]}\n", + "=== Function Output ===\n", + "['https://www.airbnb.com/rooms/10006546', 'https://www.airbnb.com/rooms/11207193']\n", + "=== LLM Response ===\n", + "Here are some Airbnb listings in Porto with a waterfront:\n", + "\n", + "1. [Listing 1](https://www.airbnb.com/rooms/10006546)\n", + "2. [Listing 2](https://www.airbnb.com/rooms/11207193)\n" + ] + } + ], + "source": [ + "response = agent.query(\"Give me listings in Porto with a Waterfront.\")" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "225f2955a7314e949f4d1fc90e0fdcb8": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_2add43683c5b4dfab0b7224bb0a4b71c", + "placeholder": "​", + "style": "IPY_MODEL_f61a6afef1d646afa11d57b57e7d573a", + "value": " 200/200 [00:00<00:00, 897.87it/s]" + } }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": { - "id": "4zCDxG4_IiiK" - }, - "outputs": [], - "source": [ - "# Convert the DataFrame to dictionary\n", - "docs = data_df.to_dict(orient=\"records\")" - ] + "2add43683c5b4dfab0b7224bb0a4b71c": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 167, - "metadata": { - "id": "uyl1ChTXIk9h" - }, - "outputs": [], - "source": [ - "llama_documents = []\n", - "fields_to_include = [\n", - " \"amenities\",\n", - " \"address\",\n", - " \"availability\",\n", - " \"review_scores\",\n", - " \"listing_url\",\n", - "]" - ] + "3a4035af32374d9f8163bd19d13504fa": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 168, - "metadata": { - "id": "AWpooso1Amft" - }, - "outputs": [], - "source": [ - "for doc in docs:\n", - " metadata = {key: doc[key] for key in fields_to_include}\n", - " llama_doc = Document(text=doc[\"description\"], metadata=metadata)\n", - " llama_documents.append(llama_doc)" - ] + "406fbc51c11344998647f5ee66901fc4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } }, - { - "cell_type": "code", - "execution_count": 169, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "dIeOtRRuJXKi", - "outputId": "3f8395c6-3cb5-4486-d9f3-c8aa062ea47f" - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Document(id_='54f8e3ba-9624-4ac4-986a-e19d67a89e7c', embedding=None, metadata={'amenities': ['TV', 'Cable TV', 'Wifi', 'Kitchen', 'Paid parking off premises', 'Smoking allowed', 'Pets allowed', 'Buzzer/wireless intercom', 'Heating', 'Family/kid friendly', 'Washer', 'First aid kit', 'Fire extinguisher', 'Essentials', 'Hangers', 'Hair dryer', 'Iron', 'Pack ’n Play/travel crib', 'Room-darkening shades', 'Hot water', 'Bed linens', 'Extra pillows and blankets', 'Microwave', 'Coffee maker', 'Refrigerator', 'Dishwasher', 'Dishes and silverware', 'Cooking basics', 'Oven', 'Stove', 'Cleaning before checkout', 'Waterfront'], 'address': {'street': 'Porto, Porto, Portugal', 'suburb': '', 'government_area': 'Cedofeita, Ildefonso, Sé, Miragaia, Nicolau, Vitória', 'market': 'Porto', 'country': 'Portugal', 'country_code': 'PT', 'location': {'type': 'Point', 'coordinates': [-8.61308, 41.1413], 'is_location_exact': False}}, 'availability': {'availability_30': 28, 'availability_60': 47, 'availability_90': 74, 'availability_365': 239}, 'review_scores': {'review_scores_accuracy': 9, 'review_scores_cleanliness': 9, 'review_scores_checkin': 10, 'review_scores_communication': 10, 'review_scores_location': 10, 'review_scores_value': 9, 'review_scores_rating': 89}, 'listing_url': 'https://www.airbnb.com/rooms/10006546'}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, text='Fantastic duplex apartment with three bedrooms, located in the historic area of Porto, Ribeira (Cube) - UNESCO World Heritage Site. Centenary building fully rehabilitated, without losing their original character. Privileged views of the Douro River and Ribeira square, our apartment offers the perfect conditions to discover the history and the charm of Porto. Apartment comfortable, charming, romantic and cozy in the heart of Ribeira. Within walking distance of all the most emblematic places of the city of Porto. The apartment is fully equipped to host 8 people, with cooker, oven, washing machine, dishwasher, microwave, coffee machine (Nespresso) and kettle. The apartment is located in a very typical area of the city that allows to cross with the most picturesque population of the city, welcoming, genuine and happy people that fills the streets with his outspoken speech and contagious with your sincere generosity, wrapped in a only parochial spirit. We are always available to help guests', mimetype='text/plain', start_char_idx=None, end_char_idx=None, text_template='{metadata_str}\\n\\n{content}', metadata_template='{key}: {value}', metadata_seperator='\\n')" - ] - }, - "execution_count": 169, - "metadata": {}, - "output_type": "execute_result" - } + "435f2a6981e64882b94cbe137eadddde": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_fce1edc87223443bb9dce94d9cd930bc", + "IPY_MODEL_9ffc973f8c8844c59c1c999746bc87b9", + "IPY_MODEL_225f2955a7314e949f4d1fc90e0fdcb8" ], - "source": [ - "llama_documents[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "dC7CDZGhzPLn" - }, - "source": [ - "## Create MongoDB Atlas Vector Store" - ] + "layout": "IPY_MODEL_f4a60ad3051942e7b1c68a8364c300e7" + } }, - { - "cell_type": "code", - "execution_count": 186, - "metadata": { - "id": "HCVyW9xGKrF3" - }, - "outputs": [], - "source": [ - "from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch\n", - "from llama_index.core import VectorStoreIndex, StorageContext\n", - "from pymongo.errors import OperationFailure" - ] - }, - { - "cell_type": "code", - "execution_count": 187, - "metadata": { - "id": "iCqflLPNBZe4" - }, - "outputs": [], - "source": [ - "DB_NAME = \"airbnb\"\n", - "COLLECTION_NAME = \"listings_reviews\"\n", - "VS_INDEX_NAME = \"vector_index\"\n", - "FTS_INDEX_NAME = \"fts_index\"\n", - "collection = mongodb_client[DB_NAME][COLLECTION_NAME]" - ] + "53be48022b114167ae066632ccfdd480": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } }, - { - "cell_type": "code", - "execution_count": 189, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 81, - "referenced_widgets": [ - "435f2a6981e64882b94cbe137eadddde", - "fce1edc87223443bb9dce94d9cd930bc", - "9ffc973f8c8844c59c1c999746bc87b9", - "225f2955a7314e949f4d1fc90e0fdcb8", - "f4a60ad3051942e7b1c68a8364c300e7", - "75ca100699444d04ae5c03d027473886", - "cfae9079f4e64e7a8798619a3aa9b4cc", - "b5e34cde4278413d977193885a74149c", - "786458928ada491eb2c9468f422b85fb", - "2add43683c5b4dfab0b7224bb0a4b71c", - "f61a6afef1d646afa11d57b57e7d573a", - "6f0165eb239e4c11bd7aff65f79b1a6b", - "975f53abc78e49088fba9a825663d91f", - "bc7980ba565f42d4bfdeeae6bf427daa", - "d101bd0c5ddd44ee91e94cb2c6df33a8", - "96e691ddb8b1472d850fe09b862101bb", - "3a4035af32374d9f8163bd19d13504fa", - "406fbc51c11344998647f5ee66901fc4", - "e0c0df23ca744bc6a123bb31b6c17915", - "d3eacb1dd8cf4d5aa85592c5806a5821", - "9a9ba8090fb74458848eeb0ea7ecea17", - "53be48022b114167ae066632ccfdd480" - ] - }, - "id": "D5sne8YMBa80", - "outputId": "38fa666c-99ed-4ff0-8f10-c7f94da8c48d" - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "435f2a6981e64882b94cbe137eadddde", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Parsing nodes: 0%| | 0/200 [00:00.\n", - "Successfully created index for model .\n" - ] - } - ], - "source": [ - "for model in [vs_model, fts_model]:\n", - " try:\n", - " collection.create_search_index(model=model)\n", - " print(f\"Successfully created index for model {model}.\")\n", - " except OperationFailure:\n", - " print(f\"Duplicate index found for model {model}. Skipping index creation.\")" - ] + "975f53abc78e49088fba9a825663d91f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_3a4035af32374d9f8163bd19d13504fa", + "placeholder": "​", + "style": "IPY_MODEL_406fbc51c11344998647f5ee66901fc4", + "value": "Generating embeddings: 100%" + } }, - { - "cell_type": "markdown", - "metadata": { - "id": "ZqjMKHMizlOM" - }, - "source": [ - "## Creating Retriever Tool for the Agent" - ] + "9a9ba8090fb74458848eeb0ea7ecea17": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 194, - "metadata": { - "id": "tHvIkj-UM72t" - }, - "outputs": [], - "source": [ - "from llama_index.core.tools import FunctionTool\n", - "from llama_index.core.vector_stores import (\n", - " MetadataFilter,\n", - " MetadataFilters,\n", - " FilterOperator,\n", - " FilterCondition,\n", - ")\n", - "from typing import List" - ] + "9ffc973f8c8844c59c1c999746bc87b9": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b5e34cde4278413d977193885a74149c", + "max": 200, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_786458928ada491eb2c9468f422b85fb", + "value": 200 + } }, - { - "cell_type": "code", - "execution_count": 195, - "metadata": { - "id": "XVz-iQDFRwnH" - }, - "outputs": [], - "source": [ - "def get_airbnb_listings(query: str, amenities: List[str]) -> str:\n", - " \"\"\"\n", - " Provides information about Airbnb listings.\n", - "\n", - " query (str): User query\n", - " amenities (List[str]): List of amenities\n", - " rating (int): Listing rating\n", - " \"\"\"\n", - " filters = [\n", - " MetadataFilter(\n", - " key=\"metadata.review_scores.review_scores_rating\",\n", - " value=80,\n", - " operator=FilterOperator.GTE,\n", - " )\n", - " ]\n", - " amenities_filter = [\n", - " MetadataFilter(\n", - " key=\"metadata.amenities\", value=amenity, operator=FilterOperator.EQ\n", - " )\n", - " for amenity in amenities\n", - " ]\n", - " filters.extend(amenities_filter)\n", - "\n", - " filters = MetadataFilters(\n", - " filters=filters,\n", - " condition=FilterCondition.AND,\n", - " )\n", - "\n", - " query_engine = vector_store_index.as_query_engine(\n", - " similarity_top_k=5, vector_store_query_mode=\"hybrid\", alpha=0.7, filters=filters\n", - " )\n", - " response = query_engine.query(query)\n", - " nodes = response.source_nodes\n", - " listings = [node.metadata[\"listing_url\"] for node in nodes]\n", - " return listings" - ] + "b5e34cde4278413d977193885a74149c": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 196, - "metadata": { - "id": "-89_2_OXTuz9" - }, - "outputs": [], - "source": [ - "query_tool = FunctionTool.from_defaults(\n", - " name=\"get_airbnb_listings\", fn=get_airbnb_listings\n", - ")" - ] + "bc7980ba565f42d4bfdeeae6bf427daa": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e0c0df23ca744bc6a123bb31b6c17915", + "max": 200, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_d3eacb1dd8cf4d5aa85592c5806a5821", + "value": 200 + } }, - { - "cell_type": "markdown", - "metadata": { - "id": "GyCMYLAB1ifQ" - }, - "source": [ - "## Create the AI Agent" - ] + "cfae9079f4e64e7a8798619a3aa9b4cc": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } }, - { - "cell_type": "code", - "execution_count": 197, - "metadata": { - "id": "13WPPB5RPR1o" - }, - "outputs": [], - "source": [ - "from llama_index.core.agent import FunctionCallingAgentWorker\n", - "from llama_index.core.agent import AgentRunner" - ] + "d101bd0c5ddd44ee91e94cb2c6df33a8": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_9a9ba8090fb74458848eeb0ea7ecea17", + "placeholder": "​", + "style": "IPY_MODEL_53be48022b114167ae066632ccfdd480", + "value": " 200/200 [00:07<00:00, 28.69it/s]" + } }, - { - "cell_type": "code", - "execution_count": 198, - "metadata": { - "id": "3JKQeSbePU-3" - }, - "outputs": [], - "source": [ - "agent_worker = FunctionCallingAgentWorker.from_tools(\n", - " [query_tool], llm=llm, verbose=True\n", - ")\n", - "agent = AgentRunner(agent_worker)" - ] + "d3eacb1dd8cf4d5aa85592c5806a5821": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } }, - { - "cell_type": "code", - "execution_count": 199, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "f0PVXC07PoCx", - "outputId": "7f4f27bb-5a5c-430e-9004-228482ca4fa8" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Added user message to memory: Give me listings in Porto with a Waterfront.\n", - "=== Calling Function ===\n", - "Calling function: get_airbnb_listings with args: {\"query\": \"Porto\", \"amenities\": [\"Waterfront\"]}\n", - "=== Function Output ===\n", - "['https://www.airbnb.com/rooms/10006546', 'https://www.airbnb.com/rooms/11207193']\n", - "=== LLM Response ===\n", - "Here are some Airbnb listings in Porto with a waterfront:\n", - "\n", - "1. [Listing 1](https://www.airbnb.com/rooms/10006546)\n", - "2. [Listing 2](https://www.airbnb.com/rooms/11207193)\n" - ] - } - ], - "source": [ - "response = agent.query(\"Give me listings in Porto with a Waterfront.\")" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] + "e0c0df23ca744bc6a123bb31b6c17915": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" + "f4a60ad3051942e7b1c68a8364c300e7": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - "language_info": { - "name": "python" + "f61a6afef1d646afa11d57b57e7d573a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } }, - "widgets": { - "application/vnd.jupyter.widget-state+json": { - "225f2955a7314e949f4d1fc90e0fdcb8": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_2add43683c5b4dfab0b7224bb0a4b71c", - "placeholder": "​", - "style": "IPY_MODEL_f61a6afef1d646afa11d57b57e7d573a", - "value": " 200/200 [00:00<00:00, 897.87it/s]" - } - }, - "2add43683c5b4dfab0b7224bb0a4b71c": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "3a4035af32374d9f8163bd19d13504fa": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "406fbc51c11344998647f5ee66901fc4": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "435f2a6981e64882b94cbe137eadddde": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_fce1edc87223443bb9dce94d9cd930bc", - "IPY_MODEL_9ffc973f8c8844c59c1c999746bc87b9", - "IPY_MODEL_225f2955a7314e949f4d1fc90e0fdcb8" - ], - "layout": "IPY_MODEL_f4a60ad3051942e7b1c68a8364c300e7" - } - }, - "53be48022b114167ae066632ccfdd480": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "6f0165eb239e4c11bd7aff65f79b1a6b": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_975f53abc78e49088fba9a825663d91f", - "IPY_MODEL_bc7980ba565f42d4bfdeeae6bf427daa", - "IPY_MODEL_d101bd0c5ddd44ee91e94cb2c6df33a8" - ], - "layout": "IPY_MODEL_96e691ddb8b1472d850fe09b862101bb" - } - }, - "75ca100699444d04ae5c03d027473886": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "786458928ada491eb2c9468f422b85fb": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "96e691ddb8b1472d850fe09b862101bb": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "975f53abc78e49088fba9a825663d91f": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_3a4035af32374d9f8163bd19d13504fa", - "placeholder": "​", - "style": "IPY_MODEL_406fbc51c11344998647f5ee66901fc4", - "value": "Generating embeddings: 100%" - } - }, - "9a9ba8090fb74458848eeb0ea7ecea17": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "9ffc973f8c8844c59c1c999746bc87b9": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_b5e34cde4278413d977193885a74149c", - "max": 200, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_786458928ada491eb2c9468f422b85fb", - "value": 200 - } - }, - "b5e34cde4278413d977193885a74149c": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "bc7980ba565f42d4bfdeeae6bf427daa": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_e0c0df23ca744bc6a123bb31b6c17915", - "max": 200, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_d3eacb1dd8cf4d5aa85592c5806a5821", - "value": 200 - } - }, - "cfae9079f4e64e7a8798619a3aa9b4cc": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "d101bd0c5ddd44ee91e94cb2c6df33a8": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_9a9ba8090fb74458848eeb0ea7ecea17", - "placeholder": "​", - "style": "IPY_MODEL_53be48022b114167ae066632ccfdd480", - "value": " 200/200 [00:07<00:00, 28.69it/s]" - } - }, - "d3eacb1dd8cf4d5aa85592c5806a5821": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "e0c0df23ca744bc6a123bb31b6c17915": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "f4a60ad3051942e7b1c68a8364c300e7": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "f61a6afef1d646afa11d57b57e7d573a": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "fce1edc87223443bb9dce94d9cd930bc": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_75ca100699444d04ae5c03d027473886", - "placeholder": "​", - "style": "IPY_MODEL_cfae9079f4e64e7a8798619a3aa9b4cc", - "value": "Parsing nodes: 100%" - } - } - } + "fce1edc87223443bb9dce94d9cd930bc": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_75ca100699444d04ae5c03d027473886", + "placeholder": "​", + "style": "IPY_MODEL_cfae9079f4e64e7a8798619a3aa9b4cc", + "value": "Parsing nodes: 100%" + } } - }, - "nbformat": 4, - "nbformat_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 } diff --git a/notebooks/agents/asset_management_analyst_assistant_agentic_chatbot_langgraph_mongodb.ipynb b/notebooks/agents/asset_management_analyst_assistant_agentic_chatbot_langgraph_mongodb.ipynb index 225a0f3..3e515b2 100644 --- a/notebooks/agents/asset_management_analyst_assistant_agentic_chatbot_langgraph_mongodb.ipynb +++ b/notebooks/agents/asset_management_analyst_assistant_agentic_chatbot_langgraph_mongodb.ipynb @@ -43,8 +43,8 @@ }, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "import os\n", "\n", "\n", "# Function to securely get and set environment variables\n", @@ -820,9 +820,8 @@ ], "source": [ "import tiktoken\n", - "import numpy as np\n", - "from tqdm import tqdm\n", "from langchain_openai import OpenAIEmbeddings\n", + "from tqdm import tqdm\n", "\n", "MAX_TOKENS = 8191 # Maximum tokens for text-embedding-3-small\n", "OVERLAP = 50\n", @@ -881,14 +880,13 @@ " if isinstance(input_data, str):\n", " # Return list of embeddings for string input\n", " return chunk_embeddings[0]\n", - " else:\n", - " # Create duplicated rows for each chunk with the respective embedding for row input\n", - " duplicated_rows = []\n", - " for embedding in chunk_embeddings:\n", - " new_row = input_data.copy()\n", - " new_row[\"embedding\"] = embedding\n", - " duplicated_rows.append(new_row)\n", - " return duplicated_rows\n", + " # Create duplicated rows for each chunk with the respective embedding for row input\n", + " duplicated_rows = []\n", + " for embedding in chunk_embeddings:\n", + " new_row = input_data.copy()\n", + " new_row[\"embedding\"] = embedding\n", + " duplicated_rows.append(new_row)\n", + " return duplicated_rows\n", "\n", "\n", "# Apply the function and expand the dataset\n", @@ -1368,8 +1366,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -1908,8 +1905,8 @@ }, "outputs": [], "source": [ - "from langchain_openai import OpenAIEmbeddings\n", "from langchain_mongodb import MongoDBAtlasVectorSearch\n", + "from langchain_openai import OpenAIEmbeddings\n", "\n", "ATLAS_VECTOR_SEARCH_INDEX = \"vector_index\"\n", "embedding_model = OpenAIEmbeddings(\n", @@ -1975,12 +1972,11 @@ "source": [ "import pickle\n", "from contextlib import AbstractContextManager\n", + "from datetime import datetime, timezone\n", "from types import TracebackType\n", - "from typing import Any, Dict, Optional, AsyncIterator, Union, List, Tuple\n", + "from typing import Any, AsyncIterator, Dict, List, Optional, Tuple, Union\n", "\n", "from langchain_core.runnables import RunnableConfig\n", - "from typing_extensions import Self\n", - "\n", "from langgraph.checkpoint.base import (\n", " BaseCheckpointSaver,\n", " Checkpoint,\n", @@ -1990,7 +1986,7 @@ ")\n", "from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer\n", "from motor.motor_asyncio import AsyncIOMotorClient\n", - "from datetime import datetime, timezone\n", + "from typing_extensions import Self\n", "\n", "\n", "class JsonPlusSerializerCompat(JsonPlusSerializer):\n", @@ -2196,8 +2192,9 @@ }, "outputs": [], "source": [ - "from typing import Dict, Any\n", - "from langchain.agents import tool, Tool\n", + "from typing import Any, Dict\n", + "\n", + "from langchain.agents import tool\n", "\n", "companies_information_collection = db.get_collection(ACTIVE_MEMORY_COLLECTION_NAME)\n", "market_report_collection = db.get_collection(MARKET_REPORT_COLLECTION_NAME)\n", @@ -2240,11 +2237,10 @@ " result += f\"Description: {company['description']}\\n\"\n", " result += f\"Address: {company['address']}\\n\\n\"\n", " return result\n", - " else:\n", - " return \"No companies found with the given criteria.\"\n", + " return \"No companies found with the given criteria.\"\n", "\n", " except Exception as e:\n", - " return f\"An error occurred while retrieving the list of companies: {str(e)}\"\n", + " return f\"An error occurred while retrieving the list of companies: {e!s}\"\n", "\n", "\n", "@tool\n", @@ -2264,8 +2260,7 @@ "\n", " if company:\n", " return f\"Company found: {company}\"\n", - " else:\n", - " return f\"No company found with the name '{company_name}'\"\n", + " return f\"No company found with the name '{company_name}'\"\n", "\n", "\n", "# def lookup_companies(query:str, n=10) -> str:\n", @@ -2290,8 +2285,7 @@ "\n", " if report:\n", " return format_market_report(report)\n", - " else:\n", - " return f\"No market report found for company '{company_name}'\"\n", + " return f\"No market report found for company '{company_name}'\"\n", "\n", "\n", "@tool\n", @@ -2310,8 +2304,7 @@ "\n", " if report:\n", " return format_market_report(report)\n", - " else:\n", - " return f\"No market report found for ticker symbol '{ticker}'\"\n", + " return f\"No market report found for ticker symbol '{ticker}'\"\n", "\n", "\n", "@tool\n", @@ -2336,8 +2329,7 @@ " formatted_results.append(f\"Similarity Score: {score}\\n{formatted_report}\\n\")\n", "\n", " return \"\\n\".join(formatted_results)\n", - " else:\n", - " return f\"No market reports found similar to the query: '{query}'\"\n", + " return f\"No market reports found similar to the query: '{query}'\"\n", "\n", "\n", "def format_market_report(report: Dict[str, Any]) -> str:\n", @@ -2521,17 +2513,18 @@ }, "outputs": [], "source": [ - "import json\n", "import base64\n", + "import json\n", "import os.path\n", - "from langchain.agents import tool\n", "from email.mime.text import MIMEText\n", - "from typing import Optional, Dict, Any\n", - "from googleapiclient.discovery import build\n", - "from googleapiclient.errors import HttpError\n", - "from google.oauth2.credentials import Credentials\n", + "from typing import Any, Dict, Optional\n", + "\n", "from google.auth.transport.requests import Request\n", + "from google.oauth2.credentials import Credentials\n", "from google_auth_oauthlib.flow import InstalledAppFlow\n", + "from googleapiclient.discovery import build\n", + "from googleapiclient.errors import HttpError\n", + "from langchain.agents import tool\n", "\n", "SCOPES = [\n", " \"https://www.googleapis.com/auth/documents\",\n", @@ -2707,7 +2700,7 @@ " return f\"Email sent successfully. Message Id: {send_message['id']}\"\n", "\n", " except Exception as error:\n", - " return f\"An error occurred: {str(error)}\"" + " return f\"An error occurred: {error!s}\"" ] }, { @@ -2768,7 +2761,7 @@ " return f\"Email sent successfully. Message Id: {send_message['id']}\"\n", "\n", " except Exception as error:\n", - " return f\"An error occurred: {str(error)}\"" + " return f\"An error occurred: {error!s}\"" ] }, { @@ -2806,7 +2799,6 @@ }, "outputs": [], "source": [ - "from langchain_openai import ChatOpenAI\n", "from langchain_anthropic import ChatAnthropic\n", "\n", "# llm = ChatOpenAI(model=\"gpt-4o\", temperature=0)\n", @@ -2833,7 +2825,6 @@ "outputs": [], "source": [ "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", - "from datetime import datetime\n", "\n", "\n", "def create_agent(llm, tools, system_message: str):\n", @@ -2946,9 +2937,10 @@ "outputs": [], "source": [ "import operator\n", - "from langchain_core.messages import BaseMessage\n", "from typing import Annotated, TypedDict\n", "\n", + "from langchain_core.messages import BaseMessage\n", + "\n", "\n", "class AgentState(TypedDict):\n", " messages: Annotated[List[BaseMessage], operator.add]\n", @@ -2973,6 +2965,7 @@ "outputs": [], "source": [ "import functools\n", + "\n", "from langchain_core.messages import AIMessage, ToolMessage\n", "\n", "\n", @@ -3119,8 +3112,8 @@ "outputs": [], "source": [ "import asyncio\n", - "from langchain_core.messages import HumanMessage, AIMessage\n", - "import time\n", + "\n", + "from langchain_core.messages import HumanMessage\n", "\n", "\n", "async def chat_loop():\n", @@ -3147,7 +3140,7 @@ " for attempt in range(max_retries):\n", " try:\n", " async for chunk in graph.astream(state, config, stream_mode=\"values\"):\n", - " if \"messages\" in chunk and chunk[\"messages\"]:\n", + " if chunk.get(\"messages\"):\n", " last_message = chunk[\"messages\"][-1]\n", " if isinstance(last_message, AIMessage):\n", " last_message.name = (\n", @@ -3162,12 +3155,12 @@ " break\n", " except Exception as e:\n", " if attempt < max_retries - 1:\n", - " print(f\"\\nAn unexpected error occurred: {str(e)}\")\n", + " print(f\"\\nAn unexpected error occurred: {e!s}\")\n", " print(f\"\\nRetrying in {retry_delay} seconds...\")\n", " await asyncio.sleep(retry_delay)\n", " retry_delay *= 2\n", " else:\n", - " print(f\"\\nMax retries reached. OpenAI API error: {str(e)}\")\n", + " print(f\"\\nMax retries reached. OpenAI API error: {e!s}\")\n", " break\n", "\n", " print(\"\\n\") # New line after the complete response" diff --git a/notebooks/agents/crewai-mdb-agg.ipynb b/notebooks/agents/crewai-mdb-agg.ipynb index 3a3c9df..d2c163e 100644 --- a/notebooks/agents/crewai-mdb-agg.ipynb +++ b/notebooks/agents/crewai-mdb-agg.ipynb @@ -174,9 +174,10 @@ "outputs": [], "source": [ "import os\n", - "import pymongo\n", "import pprint\n", "\n", + "import pymongo\n", + "\n", "# MongoDB Setup\n", "MDB_URI = \"mongodb+srv://:@cluster0.abc123.mongodb.net/\"\n", "client = pymongo.MongoClient(MDB_URI, appname=\"devrel.showcase.crewai\")\n", @@ -251,7 +252,7 @@ "outputs": [], "source": [ "# Research Agent Setup\n", - "from crewai import Crew, Process, Task, Agent\n", + "from crewai import Agent, Crew, Process, Task\n", "\n", "AGENT_ROLE = \"Investment Researcher\"\n", "AGENT_GOAL = \"\"\"\n", diff --git a/notebooks/agents/how_to_build_ai_agent_claude_3_5_sonnet_llamaindex_mongodb.ipynb b/notebooks/agents/how_to_build_ai_agent_claude_3_5_sonnet_llamaindex_mongodb.ipynb index cf17e66..aa99bba 100644 --- a/notebooks/agents/how_to_build_ai_agent_claude_3_5_sonnet_llamaindex_mongodb.ipynb +++ b/notebooks/agents/how_to_build_ai_agent_claude_3_5_sonnet_llamaindex_mongodb.ipynb @@ -128,9 +128,9 @@ }, "outputs": [], "source": [ + "from llama_index.core import Settings\n", "from llama_index.embeddings.openai import OpenAIEmbedding\n", "from llama_index.llms.anthropic import Anthropic\n", - "from llama_index.core import Settings\n", "\n", "llm = Anthropic(model=\"claude-3-5-sonnet-20240620\")\n", "\n", @@ -680,8 +680,8 @@ } ], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n", "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n", @@ -797,6 +797,7 @@ ], "source": [ "import json\n", + "\n", "from llama_index.core import Document\n", "from llama_index.core.schema import MetadataMode\n", "\n", @@ -919,7 +920,7 @@ } ], "source": [ - "from llama_index.core.node_parser import SentenceSplitter, SemanticSplitterNodeParser\n", + "from llama_index.core.node_parser import SentenceSplitter\n", "from llama_index.core.schema import MetadataMode\n", "from tqdm import tqdm\n", "\n", @@ -1034,8 +1035,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", diff --git a/notebooks/agents/how_to_build_ai_agent_openai_llamaindex_mongodb.ipynb b/notebooks/agents/how_to_build_ai_agent_openai_llamaindex_mongodb.ipynb index cf17e66..aa99bba 100644 --- a/notebooks/agents/how_to_build_ai_agent_openai_llamaindex_mongodb.ipynb +++ b/notebooks/agents/how_to_build_ai_agent_openai_llamaindex_mongodb.ipynb @@ -128,9 +128,9 @@ }, "outputs": [], "source": [ + "from llama_index.core import Settings\n", "from llama_index.embeddings.openai import OpenAIEmbedding\n", "from llama_index.llms.anthropic import Anthropic\n", - "from llama_index.core import Settings\n", "\n", "llm = Anthropic(model=\"claude-3-5-sonnet-20240620\")\n", "\n", @@ -680,8 +680,8 @@ } ], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n", "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n", @@ -797,6 +797,7 @@ ], "source": [ "import json\n", + "\n", "from llama_index.core import Document\n", "from llama_index.core.schema import MetadataMode\n", "\n", @@ -919,7 +920,7 @@ } ], "source": [ - "from llama_index.core.node_parser import SentenceSplitter, SemanticSplitterNodeParser\n", + "from llama_index.core.node_parser import SentenceSplitter\n", "from llama_index.core.schema import MetadataMode\n", "from tqdm import tqdm\n", "\n", @@ -1034,8 +1035,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", diff --git a/notebooks/agents/hr_agentic_chatbot_with_langgraph_claude.ipynb b/notebooks/agents/hr_agentic_chatbot_with_langgraph_claude.ipynb index 723a4d7..354b4ac 100644 --- a/notebooks/agents/hr_agentic_chatbot_with_langgraph_claude.ipynb +++ b/notebooks/agents/hr_agentic_chatbot_with_langgraph_claude.ipynb @@ -119,10 +119,9 @@ }, "outputs": [], "source": [ - "import pandas as pd\n", "import random\n", - "import json\n", "\n", + "import pandas as pd\n", "\n", "# Define a list of job titles and departments for variety\n", "job_titles = [\n", @@ -858,8 +857,8 @@ } ], "source": [ - "from tqdm import tqdm\n", "import openai\n", + "from tqdm import tqdm\n", "\n", "\n", "# Generate an embedding using OpenAI's API\n", @@ -1585,7 +1584,6 @@ "outputs": [], "source": [ "from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory\n", - "from langchain.memory import ConversationBufferMemory\n", "\n", "\n", "def get_session_history(session_id: str) -> MongoDBChatMessageHistory:\n", @@ -1614,7 +1612,6 @@ }, "outputs": [], "source": [ - "from langchain_openai import ChatOpenAI\n", "from langchain_anthropic import ChatAnthropic\n", "\n", "# llm = ChatOpenAI(model=\"gpt-4o-2024-05-13\", temperature=0)\n", @@ -1638,9 +1635,9 @@ }, "outputs": [], "source": [ - "from langchain_openai import OpenAIEmbeddings\n", + "from langchain.agents import tool\n", "from langchain_mongodb import MongoDBAtlasVectorSearch\n", - "from langchain.agents import tool, Tool\n", + "from langchain_openai import OpenAIEmbeddings\n", "\n", "ATLAS_VECTOR_SEARCH_INDEX = \"vector_index\"\n", "embedding_model = OpenAIEmbeddings(\n", @@ -1684,9 +1681,10 @@ }, "outputs": [], "source": [ - "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", "from datetime import datetime\n", "\n", + "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", + "\n", "\n", "def create_agent(llm, tools, system_message: str):\n", " \"\"\"Create an agent.\"\"\"\n", @@ -1748,6 +1746,7 @@ "outputs": [], "source": [ "import functools\n", + "\n", "from langchain_core.messages import AIMessage\n", "\n", "\n", @@ -1800,6 +1799,7 @@ "source": [ "import operator\n", "from typing import Annotated, Sequence, TypedDict\n", + "\n", "from langchain_core.messages import BaseMessage\n", "\n", "\n", @@ -1825,8 +1825,8 @@ }, "outputs": [], "source": [ - "from langgraph.prebuilt import tools_condition\n", "from langgraph.graph import END, StateGraph\n", + "from langgraph.prebuilt import tools_condition\n", "\n", "workflow = StateGraph(AgentState)\n", "\n", @@ -2005,8 +2005,9 @@ ], "source": [ "import pprint\n", - "from typing import List, Dict\n", - "from langchain_core.messages import BaseMessage, AIMessage, ToolMessage, HumanMessage\n", + "from typing import Dict, List\n", + "\n", + "from langchain_core.messages import BaseMessage, HumanMessage, ToolMessage\n", "\n", "events = graph.stream(\n", " {\n", diff --git a/notebooks/agents/implementing_working_memory_with_tavily_and_mongodb.ipynb b/notebooks/agents/implementing_working_memory_with_tavily_and_mongodb.ipynb index 35ecdcf..eb641c7 100644 --- a/notebooks/agents/implementing_working_memory_with_tavily_and_mongodb.ipynb +++ b/notebooks/agents/implementing_working_memory_with_tavily_and_mongodb.ipynb @@ -87,8 +87,8 @@ }, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "import os\n", "\n", "\n", "# Function to securely get and set environment variables\n", @@ -235,8 +235,8 @@ } ], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Make sure you have an HF_TOKEN in your environment varibales to access dataset on hugging face\n", "product_dataset = load_dataset(\"philschmid/amazon-product-descriptions-vlm\")\n", @@ -1814,8 +1814,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -1974,6 +1973,7 @@ "outputs": [], "source": [ "import time\n", + "\n", "from pymongo.operations import SearchIndexModel\n", "\n", "\n", @@ -2003,7 +2003,7 @@ " return result\n", "\n", " except Exception as e:\n", - " print(f\"Error creating new vector search index '{index_name}': {str(e)}\")\n", + " print(f\"Error creating new vector search index '{index_name}': {e!s}\")\n", " return None" ] }, @@ -2163,7 +2163,6 @@ }, "outputs": [], "source": [ - "from pymongo import MongoClient\n", "from tavily import TavilyHybridClient\n", "\n", "hybrid_rag = TavilyHybridClient(\n", diff --git a/notebooks/agents/mongodb_with_aws_bedrock_agent.ipynb b/notebooks/agents/mongodb_with_aws_bedrock_agent.ipynb index 67d9ceb..d5c5b52 100644 --- a/notebooks/agents/mongodb_with_aws_bedrock_agent.ipynb +++ b/notebooks/agents/mongodb_with_aws_bedrock_agent.ipynb @@ -213,11 +213,10 @@ } ], "source": [ - "import boto3\n", - "from botocore.exceptions import ClientError\n", - "import os\n", - "import random\n", "import getpass\n", + "import random\n", + "\n", + "import boto3\n", "\n", "# Get AWS credentials from user\n", "aws_access_key = getpass.getpass(\"Enter your AWS Access Key: \")\n", diff --git a/notebooks/evals/angle-embeddings-eval.ipynb b/notebooks/evals/angle-embeddings-eval.ipynb index d9d4d60..aa81993 100644 --- a/notebooks/evals/angle-embeddings-eval.ipynb +++ b/notebooks/evals/angle-embeddings-eval.ipynb @@ -71,8 +71,8 @@ }, "outputs": [], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Use streaming=True to load the dataset without downloading it fully\n", "data = load_dataset(\"MongoDB/cosmopedia-wikihow-chunked\", split=\"train\", streaming=True)\n", @@ -277,8 +277,9 @@ "outputs": [], "source": [ "from typing import List\n", - "from transformers import AutoModel, AutoTokenizer\n", - "import torch" + "\n", + "import torch\n", + "from transformers import AutoModel, AutoTokenizer" ] }, { @@ -321,7 +322,7 @@ " \"\"\"\n", " # Prepend retrieval instruction to queries\n", " if input_type == \"query\":\n", - " docs = [\"{}{}\".format(RETRIEVAL_INSTRUCT, q) for q in docs]\n", + " docs = [f\"{RETRIEVAL_INSTRUCT}{q}\" for q in docs]\n", " # Tokenize input texts\n", " inputs = tokenizer(\n", " docs, padding=True, truncation=True, return_tensors=\"pt\", max_length=512\n", diff --git a/notebooks/evals/openai-embeddings-eval.ipynb b/notebooks/evals/openai-embeddings-eval.ipynb index e8482b2..cbf3d96 100644 --- a/notebooks/evals/openai-embeddings-eval.ipynb +++ b/notebooks/evals/openai-embeddings-eval.ipynb @@ -73,8 +73,9 @@ "metadata": {}, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "import os\n", + "\n", "from openai import OpenAI" ] }, @@ -114,8 +115,8 @@ "metadata": {}, "outputs": [], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Use streaming=True to load the dataset without downloading it fully\n", "data = load_dataset(\"MongoDB/cosmopedia-wikihow-chunked\", split=\"train\", streaming=True)\n", @@ -397,8 +398,8 @@ "metadata": {}, "outputs": [], "source": [ - "from tqdm.auto import tqdm\n", - "import numpy as np" + "import numpy as np\n", + "from tqdm.auto import tqdm" ] }, { diff --git a/notebooks/evals/ragas-evaluation.ipynb b/notebooks/evals/ragas-evaluation.ipynb index 95a0cf6..f574fff 100644 --- a/notebooks/evals/ragas-evaluation.ipynb +++ b/notebooks/evals/ragas-evaluation.ipynb @@ -82,8 +82,9 @@ "metadata": {}, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "import os\n", + "\n", "from openai import OpenAI" ] }, @@ -139,8 +140,8 @@ "metadata": {}, "outputs": [], "source": [ - "from datasets import load_dataset\n", - "import pandas as pd" + "import pandas as pd\n", + "from datasets import load_dataset" ] }, { @@ -270,8 +271,9 @@ "metadata": {}, "outputs": [], "source": [ - "from langchain.text_splitter import RecursiveCharacterTextSplitter\n", - "from typing import List" + "from typing import List\n", + "\n", + "from langchain.text_splitter import RecursiveCharacterTextSplitter" ] }, { @@ -553,13 +555,13 @@ "metadata": {}, "outputs": [], "source": [ - "from langchain_openai import OpenAIEmbeddings\n", - "from langchain_mongodb import MongoDBAtlasVectorSearch\n", - "from langchain_core.vectorstores import VectorStoreRetriever\n", + "import nest_asyncio\n", "from datasets import Dataset\n", - "from ragas import evaluate, RunConfig\n", + "from langchain_core.vectorstores import VectorStoreRetriever\n", + "from langchain_mongodb import MongoDBAtlasVectorSearch\n", + "from langchain_openai import OpenAIEmbeddings\n", + "from ragas import RunConfig, evaluate\n", "from ragas.metrics import context_precision, context_recall\n", - "import nest_asyncio\n", "\n", "# Allow nested use of asyncio (used by RAGAS)\n", "nest_asyncio.apply()" @@ -734,12 +736,12 @@ "metadata": {}, "outputs": [], "source": [ - "from langchain_openai import ChatOpenAI\n", + "from langchain_core.output_parsers import StrOutputParser\n", "from langchain_core.prompts import ChatPromptTemplate\n", "from langchain_core.runnables import RunnablePassthrough\n", "from langchain_core.runnables.base import RunnableSequence\n", - "from langchain_core.output_parsers import StrOutputParser\n", - "from ragas.metrics import faithfulness, answer_relevancy" + "from langchain_openai import ChatOpenAI\n", + "from ragas.metrics import answer_relevancy, faithfulness" ] }, { @@ -921,7 +923,7 @@ "metadata": {}, "outputs": [], "source": [ - "from ragas.metrics import answer_similarity, answer_correctness" + "from ragas.metrics import answer_correctness, answer_similarity" ] }, { @@ -1327,8 +1329,8 @@ } ], "source": [ - "import seaborn as sns\n", "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", "\n", "plt.figure(figsize=(10, 8))\n", "sns.heatmap(\n", diff --git a/notebooks/evals/voyageai-embeddings-eval.ipynb b/notebooks/evals/voyageai-embeddings-eval.ipynb index 5ee3ac8..7070893 100644 --- a/notebooks/evals/voyageai-embeddings-eval.ipynb +++ b/notebooks/evals/voyageai-embeddings-eval.ipynb @@ -73,8 +73,8 @@ "metadata": {}, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "\n", "import voyageai" ] }, @@ -114,8 +114,8 @@ "metadata": {}, "outputs": [], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Use streaming=True to load the dataset without downloading it fully\n", "data = load_dataset(\"MongoDB/cosmopedia-wikihow-chunked\", split=\"train\", streaming=True)\n", diff --git a/notebooks/ml/tensorflow_mongodbcharts_horoscopes.ipynb b/notebooks/ml/tensorflow_mongodbcharts_horoscopes.ipynb index 11f8ac2..8553d12 100644 --- a/notebooks/ml/tensorflow_mongodbcharts_horoscopes.ipynb +++ b/notebooks/ml/tensorflow_mongodbcharts_horoscopes.ipynb @@ -39,13 +39,10 @@ }, "outputs": [], "source": [ - "from transformers import AutoConfig\n", - "from transformers import TFAutoModelForSequenceClassification\n", - "from transformers import AutoTokenizer\n", - "import numpy\n", "import numpy as np\n", + "import tensorflow as tf\n", "from scipy.special import softmax\n", - "import tensorflow as tf" + "from transformers import AutoConfig, AutoTokenizer, TFAutoModelForSequenceClassification" ] }, { @@ -1416,6 +1413,7 @@ "source": [ "# first connect to MongoDB Atlas\n", "import getpass\n", + "\n", "from pymongo import MongoClient\n", "\n", "# set up your MongoDB connection\n", diff --git a/notebooks/mongodb-specific/SwigMenu_Playwright_OpenAI_MongoDB.ipynb b/notebooks/mongodb-specific/SwigMenu_Playwright_OpenAI_MongoDB.ipynb index b95f6fb..5060503 100644 --- a/notebooks/mongodb-specific/SwigMenu_Playwright_OpenAI_MongoDB.ipynb +++ b/notebooks/mongodb-specific/SwigMenu_Playwright_OpenAI_MongoDB.ipynb @@ -131,7 +131,6 @@ }, "outputs": [], "source": [ - "import asyncio\n", "from playwright.async_api import async_playwright" ] }, @@ -377,9 +376,10 @@ }, "outputs": [], "source": [ - "import openai\n", + "import getpass\n", "import json\n", - "import getpass" + "\n", + "import openai" ] }, { diff --git a/notebooks/mongodb-specific/geospatialqueries_vectorsearch_spritzes.ipynb b/notebooks/mongodb-specific/geospatialqueries_vectorsearch_spritzes.ipynb index 878140a..cfb4ea8 100644 --- a/notebooks/mongodb-specific/geospatialqueries_vectorsearch_spritzes.ipynb +++ b/notebooks/mongodb-specific/geospatialqueries_vectorsearch_spritzes.ipynb @@ -92,8 +92,9 @@ }, "outputs": [], "source": [ - "import googlemaps\n", "import getpass\n", + "\n", + "import googlemaps\n", "import openai" ] }, diff --git a/notebooks/rag/Haystack_MongoDB_Atlas_RAG.ipynb b/notebooks/rag/Haystack_MongoDB_Atlas_RAG.ipynb index 6b09690..bdca8a5 100644 --- a/notebooks/rag/Haystack_MongoDB_Atlas_RAG.ipynb +++ b/notebooks/rag/Haystack_MongoDB_Atlas_RAG.ipynb @@ -234,18 +234,18 @@ }, "outputs": [], "source": [ - "from haystack import Pipeline, Document\n", - "from haystack.document_stores.types import DuplicatePolicy\n", - "from haystack.components.writers import DocumentWriter\n", - "from haystack.components.generators import OpenAIGenerator\n", + "from haystack import Document, Pipeline\n", "from haystack.components.builders.prompt_builder import PromptBuilder\n", - "from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder\n", - "from haystack_integrations.document_stores.mongodb_atlas import (\n", - " MongoDBAtlasDocumentStore,\n", - ")\n", + "from haystack.components.embedders import OpenAIDocumentEmbedder, OpenAITextEmbedder\n", + "from haystack.components.generators import OpenAIGenerator\n", + "from haystack.components.writers import DocumentWriter\n", + "from haystack.document_stores.types import DuplicatePolicy\n", "from haystack_integrations.components.retrievers.mongodb_atlas import (\n", " MongoDBAtlasEmbeddingRetriever,\n", ")\n", + "from haystack_integrations.document_stores.mongodb_atlas import (\n", + " MongoDBAtlasDocumentStore,\n", + ")\n", "\n", "# Create some example documents\n", "documents = [\n", diff --git a/notebooks/rag/TraderJoesFallAIPartyPlanner_PlaywrightLlamaIndexVectorSearch.ipynb b/notebooks/rag/TraderJoesFallAIPartyPlanner_PlaywrightLlamaIndexVectorSearch.ipynb index f713fda..2494755 100644 --- a/notebooks/rag/TraderJoesFallAIPartyPlanner_PlaywrightLlamaIndexVectorSearch.ipynb +++ b/notebooks/rag/TraderJoesFallAIPartyPlanner_PlaywrightLlamaIndexVectorSearch.ipynb @@ -140,7 +140,6 @@ }, "outputs": [], "source": [ - "import asyncio\n", "from playwright.async_api import async_playwright" ] }, @@ -546,21 +545,18 @@ }, "outputs": [], "source": [ - "import getpass, os, pymongo, pprint\n", - "from pymongo.operations import SearchIndexModel\n", - "from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, StorageContext\n", - "from llama_index.core.settings import Settings\n", - "from llama_index.core.retrievers import VectorIndexRetriever\n", - "from llama_index.core.vector_stores import (\n", - " MetadataFilter,\n", - " MetadataFilters,\n", - " ExactMatchFilter,\n", - " FilterOperator,\n", - ")\n", + "import getpass\n", + "import os\n", + "\n", + "import pymongo\n", + "from llama_index.core import SimpleDirectoryReader, StorageContext, VectorStoreIndex\n", "from llama_index.core.query_engine import RetrieverQueryEngine\n", + "from llama_index.core.retrievers import VectorIndexRetriever\n", + "from llama_index.core.settings import Settings\n", "from llama_index.embeddings.openai import OpenAIEmbedding\n", "from llama_index.llms.openai import OpenAI\n", - "from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch" + "from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch\n", + "from pymongo.operations import SearchIndexModel" ] }, { diff --git a/notebooks/rag/anthropic_mongodb_pam_ai_stack.ipynb b/notebooks/rag/anthropic_mongodb_pam_ai_stack.ipynb index fcec2e8..83b1c70 100644 --- a/notebooks/rag/anthropic_mongodb_pam_ai_stack.ipynb +++ b/notebooks/rag/anthropic_mongodb_pam_ai_stack.ipynb @@ -116,8 +116,8 @@ } ], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n", "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n", @@ -945,8 +945,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", diff --git a/notebooks/rag/building_RAG_with_LlamaIndex_and_MongoDB_Vector_Database.ipynb b/notebooks/rag/building_RAG_with_LlamaIndex_and_MongoDB_Vector_Database.ipynb index cc93cd0..1cc422e 100644 --- a/notebooks/rag/building_RAG_with_LlamaIndex_and_MongoDB_Vector_Database.ipynb +++ b/notebooks/rag/building_RAG_with_LlamaIndex_and_MongoDB_Vector_Database.ipynb @@ -44,8 +44,8 @@ }, "outputs": [], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n", "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n", @@ -79,8 +79,8 @@ "outputs": [], "source": [ "from llama_index.core.settings import Settings\n", - "from llama_index.llms.openai import OpenAI\n", "from llama_index.embeddings.openai import OpenAIEmbedding\n", + "from llama_index.llms.openai import OpenAI\n", "\n", "embed_model = OpenAIEmbedding(model=\"text-embedding-3-small\", dimensions=256)\n", "llm = OpenAI()\n", @@ -169,6 +169,7 @@ ], "source": [ "import json\n", + "\n", "from llama_index.core import Document\n", "from llama_index.core.schema import MetadataMode\n", "\n", @@ -446,6 +447,7 @@ ], "source": [ "import pprint\n", + "\n", "from llama_index.core.response.notebook_utils import display_response\n", "\n", "query_engine = index.as_query_engine(similarity_top_k=3)\n", diff --git a/notebooks/rag/chat_with_pdf_mongodb_openai_langchain_POLM_AI_Stack.ipynb b/notebooks/rag/chat_with_pdf_mongodb_openai_langchain_POLM_AI_Stack.ipynb index f268b15..f6fe5ac 100644 --- a/notebooks/rag/chat_with_pdf_mongodb_openai_langchain_POLM_AI_Stack.ipynb +++ b/notebooks/rag/chat_with_pdf_mongodb_openai_langchain_POLM_AI_Stack.ipynb @@ -110,14 +110,15 @@ ], "source": [ "import os\n", + "\n", + "from google.colab import userdata\n", + "from langchain.chains import RetrievalQA\n", + "from langchain.chat_models import ChatOpenAI\n", "from langchain.embeddings import OpenAIEmbeddings\n", + "from langchain.text_splitter import RecursiveCharacterTextSplitter\n", "from langchain.vectorstores import MongoDBAtlasVectorSearch\n", "from langchain_community.document_loaders import PyPDFLoader\n", - "from langchain.text_splitter import RecursiveCharacterTextSplitter\n", - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.chains import RetrievalQA\n", "from pymongo import MongoClient\n", - "from google.colab import userdata\n", "\n", "# Set up your OpenAI API key\n", "os.environ[\"OPENAI_API_KEY\"] = userdata.get(\"OPENAI_API_KEY\")\n", diff --git a/notebooks/rag/graphrag_with_mongodb_and_openai.ipynb b/notebooks/rag/graphrag_with_mongodb_and_openai.ipynb index 529cd0b..8ff96fd 100644 --- a/notebooks/rag/graphrag_with_mongodb_and_openai.ipynb +++ b/notebooks/rag/graphrag_with_mongodb_and_openai.ipynb @@ -47,8 +47,8 @@ }, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "import os\n", "\n", "\n", "# Function to securely get and set environment variables\n", @@ -565,7 +565,7 @@ "\n", " return summary\n", " except Exception as e:\n", - " return f\"Error summarizing data: {str(e)}\"" + " return f\"Error summarizing data: {e!s}\"" ] }, { @@ -1595,8 +1595,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -2951,6 +2950,7 @@ "outputs": [], "source": [ "import time\n", + "\n", "from pymongo.operations import SearchIndexModel\n", "\n", "\n", @@ -2980,7 +2980,7 @@ " return result\n", "\n", " except Exception as e:\n", - " print(f\"Error creating new vector search index '{index_name}': {str(e)}\")\n", + " print(f\"Error creating new vector search index '{index_name}': {e!s}\")\n", " return None" ] }, @@ -3132,8 +3132,7 @@ "\n", " # Extract and return the OpenAI's response\n", " return response.choices[0].message.content\n", - " else:\n", - " return \"No relevant employees found for this query.\"" + " return \"No relevant employees found for this query.\"" ] }, { @@ -3276,7 +3275,7 @@ " result = list(collection.aggregate(pipeline))\n", " return result\n", " except Exception as e:\n", - " print(f\"An error occurred: {str(e)}\")\n", + " print(f\"An error occurred: {e!s}\")\n", " return []" ] }, @@ -3520,8 +3519,7 @@ "\n", " # Extract and return the OpenAI's response\n", " return response.choices[0].message.content\n", - " else:\n", - " return \"No relevant employees found for this query.\"" + " return \"No relevant employees found for this query.\"" ] }, { diff --git a/notebooks/rag/haystack_mongodb_cooking_advisor_pipeline.ipynb b/notebooks/rag/haystack_mongodb_cooking_advisor_pipeline.ipynb index f7bc85c..e53a9ed 100644 --- a/notebooks/rag/haystack_mongodb_cooking_advisor_pipeline.ipynb +++ b/notebooks/rag/haystack_mongodb_cooking_advisor_pipeline.ipynb @@ -161,8 +161,8 @@ "outputs": [], "source": [ "import getpass\n", - "import re\n", - "import os" + "import os\n", + "import re" ] }, { @@ -268,20 +268,19 @@ }, "outputs": [], "source": [ - "from haystack import Pipeline, Document\n", - "from haystack.document_stores.types import DuplicatePolicy\n", - "from haystack.components.writers import DocumentWriter\n", - "from haystack.components.generators import OpenAIGenerator\n", + "from bson import json_util\n", + "from haystack import Document, Pipeline\n", "from haystack.components.builders.prompt_builder import PromptBuilder\n", - "from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder\n", - "from haystack_integrations.document_stores.mongodb_atlas import (\n", - " MongoDBAtlasDocumentStore,\n", - ")\n", + "from haystack.components.embedders import OpenAIDocumentEmbedder, OpenAITextEmbedder\n", + "from haystack.components.generators import OpenAIGenerator\n", + "from haystack.components.writers import DocumentWriter\n", + "from haystack.document_stores.types import DuplicatePolicy\n", "from haystack_integrations.components.retrievers.mongodb_atlas import (\n", " MongoDBAtlasEmbeddingRetriever,\n", ")\n", - "from datasets import load_dataset\n", - "from bson import json_util\n", + "from haystack_integrations.document_stores.mongodb_atlas import (\n", + " MongoDBAtlasDocumentStore,\n", + ")\n", "\n", "# Create some example documents\n", "# documents = [\n", diff --git a/notebooks/rag/mongodb-langchain-cache-memory.ipynb b/notebooks/rag/mongodb-langchain-cache-memory.ipynb index 8da1164..64550fd 100644 --- a/notebooks/rag/mongodb-langchain-cache-memory.ipynb +++ b/notebooks/rag/mongodb-langchain-cache-memory.ipynb @@ -147,8 +147,8 @@ "metadata": {}, "outputs": [], "source": [ - "from datasets import load_dataset\n", - "import pandas as pd" + "import pandas as pd\n", + "from datasets import load_dataset" ] }, { @@ -374,8 +374,8 @@ "metadata": {}, "outputs": [], "source": [ - "from pymongo import MongoClient\n", "from langchain_mongodb import MongoDBAtlasVectorSearch\n", + "from pymongo import MongoClient\n", "\n", "# Initialize MongoDB python client\n", "client = MongoClient(MONGODB_URI, appname=\"devrel.content.python\")\n", @@ -480,10 +480,10 @@ "metadata": {}, "outputs": [], "source": [ - "from langchain_openai import ChatOpenAI\n", + "from langchain_core.output_parsers import StrOutputParser\n", "from langchain_core.prompts import ChatPromptTemplate\n", "from langchain_core.runnables import RunnablePassthrough\n", - "from langchain_core.output_parsers import StrOutputParser\n", + "from langchain_openai import ChatOpenAI\n", "\n", "# Generate context using the retriever, and pass the user question through\n", "retrieve = {\n", @@ -542,9 +542,9 @@ "metadata": {}, "outputs": [], "source": [ - "from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory\n", + "from langchain_core.prompts import MessagesPlaceholder\n", "from langchain_core.runnables.history import RunnableWithMessageHistory\n", - "from langchain_core.prompts import MessagesPlaceholder" + "from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory" ] }, { @@ -728,8 +728,8 @@ "metadata": {}, "outputs": [], "source": [ - "from langchain_mongodb.cache import MongoDBAtlasSemanticCache\n", "from langchain_core.globals import set_llm_cache\n", + "from langchain_mongodb.cache import MongoDBAtlasSemanticCache\n", "\n", "set_llm_cache(\n", " MongoDBAtlasSemanticCache(\n", diff --git a/notebooks/rag/naive_rag_implemenation_llamaindex.ipynb b/notebooks/rag/naive_rag_implemenation_llamaindex.ipynb index e0b3e72..fe6a18b 100644 --- a/notebooks/rag/naive_rag_implemenation_llamaindex.ipynb +++ b/notebooks/rag/naive_rag_implemenation_llamaindex.ipynb @@ -488,8 +488,8 @@ } ], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# https://huggingface.co/datasets/MongoDB/embedded_movies\n", "dataset = load_dataset(\"MongoDB/embedded_movies\")\n", @@ -978,8 +978,8 @@ "outputs": [], "source": [ "from llama_index.core.settings import Settings\n", - "from llama_index.llms.openai import OpenAI\n", "from llama_index.embeddings.openai import OpenAIEmbedding\n", + "from llama_index.llms.openai import OpenAI\n", "\n", "embed_model = OpenAIEmbedding(model=\"text-embedding-3-small\", dimensions=256)\n", "llm = OpenAI()\n", @@ -1042,6 +1042,7 @@ ], "source": [ "import json\n", + "\n", "from llama_index.core import Document\n", "from llama_index.core.schema import MetadataMode\n", "\n", @@ -1263,7 +1264,7 @@ }, "outputs": [], "source": [ - "from llama_index.core import VectorStoreIndex, StorageContext\n", + "from llama_index.core import VectorStoreIndex\n", "\n", "index = VectorStoreIndex.from_vector_store(vector_store)" ] @@ -1304,6 +1305,7 @@ ], "source": [ "import pprint\n", + "\n", "from llama_index.core.response.notebook_utils import display_response\n", "\n", "query_engine = index.as_query_engine(similarity_top_k=3)\n", diff --git a/notebooks/rag/openai_text_3_emebdding.ipynb b/notebooks/rag/openai_text_3_emebdding.ipynb index c6cc153..d44b598 100644 --- a/notebooks/rag/openai_text_3_emebdding.ipynb +++ b/notebooks/rag/openai_text_3_emebdding.ipynb @@ -695,8 +695,8 @@ ], "source": [ "# 1. Load Dataset\n", - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# https://huggingface.co/datasets/MongoDB/embedded_movies\n", "dataset = load_dataset(\"MongoDB/embedded_movies\")\n", diff --git a/notebooks/rag/rag_chatbot_with_cohere_and_mongodb.ipynb b/notebooks/rag/rag_chatbot_with_cohere_and_mongodb.ipynb index a2f4146..03d6dbf 100644 --- a/notebooks/rag/rag_chatbot_with_cohere_and_mongodb.ipynb +++ b/notebooks/rag/rag_chatbot_with_cohere_and_mongodb.ipynb @@ -123,6 +123,7 @@ "outputs": [], "source": [ "import os\n", + "\n", "import cohere\n", "\n", "os.environ[\"COHERE_API_KEY\"] = \"\"\n", @@ -1404,8 +1405,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -1983,7 +1983,6 @@ } ], "source": [ - "import pprint\n", "\n", "query = \"What companies have negative market reports or negative sentiment that might deter from investment in the long term\"\n", "\n", @@ -2439,7 +2438,7 @@ }, "outputs": [], "source": [ - "from typing import Dict, Optional, List\n", + "from typing import Dict, List, Optional\n", "\n", "\n", "class CohereChat:\n", diff --git a/notebooks/rag/rag_chunking_strategies.ipynb b/notebooks/rag/rag_chunking_strategies.ipynb index e2ecf2d..d13ade7 100644 --- a/notebooks/rag/rag_chunking_strategies.ipynb +++ b/notebooks/rag/rag_chunking_strategies.ipynb @@ -55,8 +55,9 @@ "metadata": {}, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "import os\n", + "\n", "from openai import OpenAI" ] }, @@ -145,15 +146,16 @@ "metadata": {}, "outputs": [], "source": [ + "from typing import Dict, List, Optional\n", + "\n", "from langchain.text_splitter import (\n", " Language,\n", " RecursiveCharacterTextSplitter,\n", " TokenTextSplitter,\n", ")\n", - "from langchain_experimental.text_splitter import SemanticChunker\n", - "from langchain_openai.embeddings import OpenAIEmbeddings\n", "from langchain_core.documents import Document\n", - "from typing import Dict, List, Optional" + "from langchain_experimental.text_splitter import SemanticChunker\n", + "from langchain_openai.embeddings import OpenAIEmbeddings" ] }, { @@ -215,7 +217,7 @@ " separators = RecursiveCharacterTextSplitter.get_separators_for_language(\n", " language\n", " )\n", - " except (NameError, ValueError) as e:\n", + " except (NameError, ValueError):\n", " print(f\"No separators found for language {language}. Using defaults.\")\n", "\n", " splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(\n", @@ -265,10 +267,10 @@ "metadata": {}, "outputs": [], "source": [ + "from langchain_openai import ChatOpenAI, OpenAIEmbeddings\n", "from ragas import RunConfig\n", + "from ragas.testset.evolutions import multi_context, reasoning, simple\n", "from ragas.testset.generator import TestsetGenerator\n", - "from ragas.testset.evolutions import simple, reasoning, multi_context\n", - "from langchain_openai import ChatOpenAI, OpenAIEmbeddings\n", "\n", "RUN_CONFIG = RunConfig(max_workers=4, max_wait=180)" ] @@ -518,11 +520,11 @@ "metadata": {}, "outputs": [], "source": [ - "from tqdm import tqdm\n", + "import nest_asyncio\n", "from datasets import Dataset\n", "from ragas import evaluate\n", "from ragas.metrics import context_precision, context_recall\n", - "import nest_asyncio\n", + "from tqdm import tqdm\n", "\n", "# Allow nested use of asyncio (used by RAGAS)\n", "nest_asyncio.apply()\n", @@ -559,11 +561,11 @@ "\n", " print(f\"Deleting existing documents in the collection {DB_NAME}.{COLLECTION_NAME}\")\n", " MONGODB_COLLECTION.delete_many({})\n", - " print(f\"Deletion complete\")\n", + " print(\"Deletion complete\")\n", " vector_store = create_vector_store(docs)\n", "\n", " # Getting relevant documents for questions in the evaluation dataset\n", - " print(f\"Getting contexts for evaluation set\")\n", + " print(\"Getting contexts for evaluation set\")\n", " for question in tqdm(QUESTIONS):\n", " eval_data[\"contexts\"].append(\n", " [doc.page_content for doc in vector_store.similarity_search(question, k=3)]\n", @@ -571,7 +573,7 @@ " # RAGAS expects a Dataset object\n", " dataset = Dataset.from_dict(eval_data)\n", "\n", - " print(f\"Running evals\")\n", + " print(\"Running evals\")\n", " result = evaluate(\n", " dataset=dataset,\n", " metrics=[context_precision, context_recall],\n", diff --git a/notebooks/rag/rag_mongodb_llama3_huggingface_open_source.ipynb b/notebooks/rag/rag_mongodb_llama3_huggingface_open_source.ipynb index 4d49917..8475419 100644 --- a/notebooks/rag/rag_mongodb_llama3_huggingface_open_source.ipynb +++ b/notebooks/rag/rag_mongodb_llama3_huggingface_open_source.ipynb @@ -92,10 +92,11 @@ "outputs": [], "source": [ "# Load Dataset\n", - "from datasets import load_dataset\n", - "import pandas as pd\n", "import os\n", "\n", + "import pandas as pd\n", + "from datasets import load_dataset\n", + "\n", "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n", "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n", "# Dataset Location: https://huggingface.co/datasets/MongoDB/subset_arxiv_papers_with_embeddings\n", @@ -939,8 +940,8 @@ } ], "source": [ - "from transformers import AutoTokenizer, AutoModelForCausalLM\n", "import torch\n", + "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(\"meta-llama/Meta-Llama-3-8B-Instruct\")\n", "# CPU Enabled uncomment below 👇🏽\n", diff --git a/notebooks/rag/rag_pipeline_kerasnlp_mongodb_gemma2.ipynb b/notebooks/rag/rag_pipeline_kerasnlp_mongodb_gemma2.ipynb index 53fa2dc..8f535d7 100644 --- a/notebooks/rag/rag_pipeline_kerasnlp_mongodb_gemma2.ipynb +++ b/notebooks/rag/rag_pipeline_kerasnlp_mongodb_gemma2.ipynb @@ -538,8 +538,8 @@ ], "source": [ "# Load Dataset\n", - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n", "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n", @@ -1110,8 +1110,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -1339,8 +1338,9 @@ "outputs": [], "source": [ "import textwrap\n", - "import keras_nlp\n", + "\n", "import keras\n", + "import keras_nlp\n", "from IPython.display import Markdown\n", "\n", "# Run at half precision.\n", @@ -1369,7 +1369,6 @@ }, "outputs": [], "source": [ - "import pymongo\n", "from typing import Dict, Optional\n", "\n", "\n", @@ -1722,7 +1721,7 @@ "source": [ "# Testing Gemma\n", "%time result = gemma_lm.generate(\"What are your current capabilities?\", max_length=256)\n", - "to_markdown(result)" + "to_markdown(result) # noqa: F821" ] }, { diff --git a/notebooks/rag/rag_with_gemma2_2b_mongodb_open_models.ipynb b/notebooks/rag/rag_with_gemma2_2b_mongodb_open_models.ipynb index f7d42b7..e6e6413 100644 --- a/notebooks/rag/rag_with_gemma2_2b_mongodb_open_models.ipynb +++ b/notebooks/rag/rag_with_gemma2_2b_mongodb_open_models.ipynb @@ -147,8 +147,8 @@ } ], "source": [ - "import os\n", "import getpass\n", + "import os\n", "\n", "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n", "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n", @@ -944,7 +944,6 @@ "source": [ "from sentence_transformers import SentenceTransformer\n", "from tqdm import tqdm\n", - "import numpy as np\n", "\n", "# Load the model\n", "# https://huggingface.co/thenlper/gte-large\n", @@ -996,14 +995,13 @@ " if isinstance(input_data, str):\n", " # Return list of embeddings for string input\n", " return [embedding.tolist() for embedding in chunk_embeddings][0]\n", - " else:\n", - " # Create duplicated rows for each chunk with the respective embedding for row input\n", - " duplicated_rows = []\n", - " for embedding in chunk_embeddings:\n", - " new_row = input_data.copy()\n", - " new_row[\"embedding\"] = embedding.tolist()\n", - " duplicated_rows.append(new_row)\n", - " return duplicated_rows" + " # Create duplicated rows for each chunk with the respective embedding for row input\n", + " duplicated_rows = []\n", + " for embedding in chunk_embeddings:\n", + " new_row = input_data.copy()\n", + " new_row[\"embedding\"] = embedding.tolist()\n", + " duplicated_rows.append(new_row)\n", + " return duplicated_rows" ] }, { @@ -1487,8 +1485,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -1604,6 +1601,7 @@ "source": [ "# Programmatically create vector search index for colelctions\n", "import time\n", + "\n", "from pymongo.operations import SearchIndexModel\n", "\n", "\n", @@ -1633,7 +1631,7 @@ " return result\n", "\n", " except Exception as e:\n", - " print(f\"Error creating new vector search index '{index_name}': {str(e)}\")\n", + " print(f\"Error creating new vector search index '{index_name}': {e!s}\")\n", " return None" ] }, @@ -2278,7 +2276,7 @@ ], "source": [ "import torch\n", - "from transformers import AutoTokenizer, AutoModelForCausalLM\n", + "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(\"google/gemma-2-2b-it\")\n", "model = AutoModelForCausalLM.from_pretrained(\n", @@ -2306,8 +2304,7 @@ " model_response = model_response.split(\"\")[0].strip()\n", "\n", " return model_response\n", - " else:\n", - " return \"No model response found.\"" + " return \"No model response found.\"" ] }, { @@ -2392,7 +2389,6 @@ }, "outputs": [], "source": [ - "from deepeval import evaluate\n", "from deepeval.test_case import LLMTestCase" ] }, @@ -2953,8 +2949,7 @@ "\n", " if score > threshold:\n", " return True, score # Content violates the policy\n", - " else:\n", - " return False, score # Content does not violate the policy\n", + " return False, score # Content does not violate the policy\n", "\n", "\n", "# Example usage\n", diff --git a/notebooks/rag/rag_with_gemma2_mongodb_open_models.ipynb b/notebooks/rag/rag_with_gemma2_mongodb_open_models.ipynb index 80a2877..c6fc010 100644 --- a/notebooks/rag/rag_with_gemma2_mongodb_open_models.ipynb +++ b/notebooks/rag/rag_with_gemma2_mongodb_open_models.ipynb @@ -559,8 +559,8 @@ ], "source": [ "# Load Dataset\n", - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# Make sure you have an Hugging Face token(HF_TOKEN) in your development environemnt before running the code below\n", "# How to get a token: https://huggingface.co/docs/hub/en/security-tokens\n", @@ -1911,7 +1911,6 @@ ], "source": [ "import pymongo\n", - "from google.colab import userdata\n", "\n", "\n", "def get_mongo_client(mongo_uri):\n", @@ -1925,8 +1924,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -2487,7 +2485,7 @@ ], "source": [ "import torch\n", - "from transformers import AutoTokenizer, AutoModelForCausalLM\n", + "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(\"google/gemma-2-9b-it\")\n", "model = AutoModelForCausalLM.from_pretrained(\n", diff --git a/notebooks/rag/rag_with_hugging_face_gemma_mongodb.ipynb b/notebooks/rag/rag_with_hugging_face_gemma_mongodb.ipynb index 440f0f2..a9d8b63 100644 --- a/notebooks/rag/rag_with_hugging_face_gemma_mongodb.ipynb +++ b/notebooks/rag/rag_with_hugging_face_gemma_mongodb.ipynb @@ -484,8 +484,8 @@ ], "source": [ "# Load Dataset\n", - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "\n", "# https://huggingface.co/datasets/MongoDB/embedded_movies\n", "dataset = load_dataset(\"MongoDB/embedded_movies\")\n", @@ -1747,7 +1747,7 @@ }, "outputs": [], "source": [ - "from transformers import AutoTokenizer, AutoModelForCausalLM\n", + "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(\"google/gemma-2b-it\")\n", "# CPU Enabled uncomment below 👇🏽\n", diff --git a/notebooks/rag/self_querying_mongodb_unstructured_langgraph.ipynb b/notebooks/rag/self_querying_mongodb_unstructured_langgraph.ipynb index 5d04d1f..8faaa5c 100644 --- a/notebooks/rag/self_querying_mongodb_unstructured_langgraph.ipynb +++ b/notebooks/rag/self_querying_mongodb_unstructured_langgraph.ipynb @@ -91,6 +91,7 @@ "outputs": [], "source": [ "import os\n", + "\n", "from openai import OpenAI\n", "from pymongo import MongoClient" ] @@ -217,16 +218,14 @@ }, "outputs": [], "source": [ - "from unstructured_ingest.v2.pipeline.pipeline import Pipeline\n", "from unstructured_ingest.v2.interfaces import ProcessorConfig\n", - "from unstructured_ingest.v2.processes.partitioner import PartitionerConfig\n", + "from unstructured_ingest.v2.pipeline.pipeline import Pipeline\n", "from unstructured_ingest.v2.processes.chunker import ChunkerConfig\n", - "from unstructured_ingest.v2.processes.embedder import EmbedderConfig\n", "from unstructured_ingest.v2.processes.connectors.fsspec.s3 import (\n", + " S3AccessConfig,\n", " S3ConnectionConfig,\n", " S3DownloaderConfig,\n", " S3IndexerConfig,\n", - " S3AccessConfig,\n", ")\n", "\n", "# For pipeline using a local source\n", @@ -235,7 +234,9 @@ "# LocalDownloaderConfig,\n", "# LocalConnectionConfig,\n", "# )\n", - "from unstructured_ingest.v2.processes.connectors.local import LocalUploaderConfig" + "from unstructured_ingest.v2.processes.connectors.local import LocalUploaderConfig\n", + "from unstructured_ingest.v2.processes.embedder import EmbedderConfig\n", + "from unstructured_ingest.v2.processes.partitioner import PartitionerConfig" ] }, { @@ -323,8 +324,8 @@ }, "outputs": [], "source": [ - "import re\n", - "import json" + "import json\n", + "import re" ] }, { @@ -358,7 +359,7 @@ " year = match.group(0)[-4:]\n", " try:\n", " year = int(year)\n", - " except:\n", + " except Exception:\n", " year = 0\n", " return year" ] @@ -446,7 +447,7 @@ " file_path = os.path.join(directory, filename)\n", " print(f\"Processing file {filename}\")\n", " try:\n", - " with open(file_path, \"r\") as file:\n", + " with open(file_path) as file:\n", " data = json.load(file)\n", "\n", " company_name = get_company_name(data)\n", @@ -464,7 +465,7 @@ " print(f\"Successfully updated {file_path} with custom metadata fields.\")\n", " except json.JSONDecodeError as e:\n", " print(f\"Error parsing JSON in {file_path}: {e}\")\n", - " except IOError as e:\n", + " except OSError as e:\n", " print(f\"Error reading from or writing to {file_path}: {e}\")" ] }, @@ -490,10 +491,10 @@ "outputs": [], "source": [ "from unstructured_ingest.v2.processes.connectors.mongodb import (\n", + " MongoDBAccessConfig,\n", " MongoDBConnectionConfig,\n", - " MongoDBUploadStagerConfig,\n", " MongoDBUploaderConfig,\n", - " MongoDBAccessConfig,\n", + " MongoDBUploadStagerConfig,\n", ")" ] }, @@ -576,9 +577,10 @@ }, "outputs": [], "source": [ - "from typing_extensions import TypedDict\n", + "from typing import Annotated, Dict, List\n", + "\n", "from langgraph.graph.message import add_messages\n", - "from typing import Annotated, List, Dict" + "from typing_extensions import TypedDict" ] }, { @@ -642,8 +644,9 @@ }, "outputs": [], "source": [ - "from pydantic import BaseModel, Field\n", - "from datetime import datetime" + "from datetime import datetime\n", + "\n", + "from pydantic import BaseModel, Field" ] }, { @@ -942,7 +945,7 @@ }, "outputs": [], "source": [ - "from langchain_core.messages import HumanMessage, AIMessage" + "from langchain_core.messages import AIMessage, HumanMessage" ] }, { @@ -967,7 +970,7 @@ " question = state[\"question\"]\n", " context = state[\"context\"]\n", " memory = state[\"memory\"]\n", - " system = f\"Answer the question based only on the following context. If the context is empty or if it doesn't provide enough information to answer the question, say I DON'T KNOW\"\n", + " system = \"Answer the question based only on the following context. If the context is empty or if it doesn't provide enough information to answer the question, say I DON'T KNOW\"\n", " completion = openai_client.chat.completions.create(\n", " model=COMPLETION_MODEL_NAME,\n", " temperature=0,\n", @@ -1020,9 +1023,8 @@ " print(\"---DECISION: SKIP TO VECTOR SEARCH---\")\n", " return \"vector_search\"\n", " # If metadata is extracted, generate filter definition\n", - " else:\n", - " print(\"---DECISION: GENERATE FILTER---\")\n", - " return \"generate_filter\"" + " print(\"---DECISION: GENERATE FILTER---\")\n", + " return \"generate_filter\"" ] }, { @@ -1044,9 +1046,9 @@ }, "outputs": [], "source": [ - "from langgraph.graph import END, StateGraph, START\n", + "from IPython.display import Image, display\n", "from langgraph.checkpoint.memory import MemorySaver\n", - "from IPython.display import Image, display" + "from langgraph.graph import END, START, StateGraph" ] }, { diff --git a/notebooks/techniques/advanced_evaluation_of_quantized_vectors_using_cohere_mongodb_beir.ipynb b/notebooks/techniques/advanced_evaluation_of_quantized_vectors_using_cohere_mongodb_beir.ipynb index 91a2fc0..a77d65d 100644 --- a/notebooks/techniques/advanced_evaluation_of_quantized_vectors_using_cohere_mongodb_beir.ipynb +++ b/notebooks/techniques/advanced_evaluation_of_quantized_vectors_using_cohere_mongodb_beir.ipynb @@ -87,10 +87,10 @@ }, "outputs": [], "source": [ - "from beir import util, LoggingHandler\n", + "import pandas as pd\n", + "from beir import util\n", "from beir.datasets.data_loader import GenericDataLoader\n", "from beir.retrieval.evaluation import EvaluateRetrieval\n", - "import pandas as pd\n", "\n", "\n", "# Load BEIR dataset\n", @@ -599,9 +599,10 @@ } ], "source": [ + "import getpass\n", "import os\n", + "\n", "import cohere\n", - "import getpass\n", "\n", "# You are going to need a production API key due to rate limiting on free tier\n", "COHERE_API_KEY = getpass.getpass(\"Enter Cohere API Key: \")\n", @@ -616,7 +617,6 @@ }, "outputs": [], "source": [ - "import cohere\n", "\n", "# Initialize Cohere Client\n", "co = cohere.Client(COHERE_API_KEY)" @@ -1512,8 +1512,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -1535,7 +1534,7 @@ " result = collection.insert_many(documents)\n", " print(f\"Inserted {len(result.inserted_ids)} documents into {collection.name}\")\n", " except Exception as e:\n", - " print(f\"Error inserting documents into {collection.name}: {str(e)}\")" + " print(f\"Error inserting documents into {collection.name}: {e!s}\")" ] }, { @@ -1679,6 +1678,7 @@ "source": [ "# Programmatically create vector search index for both colelctions\n", "import time\n", + "\n", "from pymongo.operations import SearchIndexModel\n", "\n", "\n", @@ -1708,7 +1708,7 @@ " return result\n", "\n", " except Exception as e:\n", - " print(f\"Error creating new vector search index '{index_name}': {str(e)}\")\n", + " print(f\"Error creating new vector search index '{index_name}': {e!s}\")\n", " return None" ] }, @@ -2425,11 +2425,10 @@ }, "outputs": [], "source": [ - "import time\n", "from typing import Dict\n", - "from pymongo.collection import Collection\n", + "\n", "from beir.retrieval.search.base import BaseSearch\n", - "from beir.retrieval.evaluation import EvaluateRetrieval\n", + "from pymongo.collection import Collection\n", "\n", "\n", "class MongoDBVectorSearch(BaseSearch):\n", @@ -3034,7 +3033,6 @@ "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", - "import numpy as np\n", "\n", "\n", "def plot_search_method_comparison(metric_dicts_list):\n", diff --git a/notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb b/notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb index 06ee2bd..000f348 100644 --- a/notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb +++ b/notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb @@ -1,3861 +1,3866 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "oB0TFkwoNsv7" - }, - "source": [ - "# Information Retrieval Evaluation With BEIR Benchmark and LangChain and MongoDB\n", - "\n", - "\n", - "---\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "TScxhzzCoi9q" - }, - "source": [ - "# **Step 1: Install Libraires and Set Environment Variables**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "PqqPt3h_UbeG" - }, - "outputs": [], - "source": [ - "!pip install -q openai pymongo langchain langchain_mongodb langchain_openai beir" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "Bs3Safw_Uj00", - "outputId": "5644eb4e-1132-483c-a8ac-b8fce85da591" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Enter OpenAI API Key: ··········\n" - ] - } - ], - "source": [ - "import os\n", - "import json\n", - "import getpass\n", - "\n", - "OPENAI_API_KEY = getpass.getpass(\"Enter OpenAI API Key: \")\n", - "os.environ[\"OPENAI_API_KEY\"] = OPENAI_API_KEY\n", - "\n", - "GPT_MODEL = \"gpt-4o-2024-08-06\"\n", - "\n", - "# Areas for optimisation of RAG Pipelines associated with chunking strategy\n", - "EMBEDDING_MODEL = \"text-embedding-3-small\"\n", - "EMBEDDING_DIMENSION_SIZE = 256" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "g0GJ9efPUtfA", - "outputId": "1bc3addc-a31e-4a16-9dba-d3486679a419" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Enter MongoDB URI: ··········\n" - ] - } - ], - "source": [ - "MONGO_URI = getpass.getpass(\"Enter MongoDB URI: \")\n", - "os.environ[\"MONGO_URI\"] = MONGO_URI" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "qa2Bn-N-pp9a" - }, - "outputs": [], - "source": [ - "metric_names = [\"NDCG\", \"MAP\", \"Recall\", \"Precision\"]\n", - "information_retrieval_search_methods = ['Lexical', 'Vector', 'Hybrid']" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "rn4FIfvSo33q" - }, - "source": [ - "# **Step 2: Data Loading**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "jMYkRQwiVag2", - "outputId": "e26784b4-e0fe-48d4-b8e3-9bff5a0c3ad0" - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/usr/local/lib/python3.10/dist-packages/beir/util.py:2: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)\n", - " from tqdm.autonotebook import tqdm\n" - ] - } - ], - "source": [ - "from beir import util, LoggingHandler\n", - "from beir.datasets.data_loader import GenericDataLoader\n", - "from beir.retrieval.evaluation import EvaluateRetrieval\n", - "import pandas as pd\n", - "\n", - "# Load BEIR dataset\n", - "def load_beir_dataset(dataset_name=\"scifact\"):\n", - " url = f\"https://public.ukp.informatik.tu-darmstadt.de/thakur/BEIR/datasets/{dataset_name}.zip\"\n", - " data_path = util.download_and_unzip(url, \"datasets\")\n", - " corpus, queries, qrels = GenericDataLoader(data_folder=data_path).load(split=\"test\")\n", - " return corpus, queries, qrels" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 81, - "referenced_widgets": [ - "51c3a472109243c681898fb32aeda7d7", - "f22b82b8010a4a79b0b42908966cc89e", - "35b668058eca435a86829f32ca421859", - "84d25add023044d68f383b81dacaf462", - "c3375ea1a272481babcaece7f79b428e", - "6770f34c4be644cda13221e47d00ca28", - "c2c384a4406b4b9f9dfc57779d7246ee", - "33ef6c005a52428cb00a9e7ccb0e6b2c", - "b8c4d550a4fb475d8a66c1e5deefb1f2", - "c45d82a40d2c4096b6c00b6c93290add", - "9cbf8f18e9dd4cd3acc274ad3f4868ae", - "73cddc3fa8bb4495b335018fae3b063e", - "4950b546681b4c8cbec0a9c3acf08c37", - "30ccab778b894d8c86359fb850ee76f2", - "c25ebc49169a4fccae65c84ba71b50c7", - "00135b96c1e34abf94352e5d14dfbfc2", - "350c3f298a7b414c8ab6ea4492fb98c3", - "6275b672934d4cc383cc4c18f3dfe4b7", - "b7df766690574c09b4942e0d27151171", - "e65a397cb2e44371886c3f51362a9bc6", - "7350acfbe3bd4e1cb4ff49290a6cd58f", - "5b4d7df8ac4e4a788d7684f47f1d1b76" - ] - }, - "id": "si-mKb3ozi11", - "outputId": "49973c88-3d9a-485e-ceb5-c80bd4c69330" - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "51c3a472109243c681898fb32aeda7d7", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "datasets/scifact.zip: 0%| | 0.00/2.69M [00:00MongoDB Integration" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "_a_inIiFAhBo" - }, - "outputs": [], - "source": [ - "# Test lexical search with MongoDB Atlas\n", - "from typing import List, Tuple, Any\n", - "from langchain.schema import Document\n", - "from langchain_mongodb.retrievers import MongoDBAtlasFullTextSearchRetriever\n", - "\n", - "def full_text_search(collection, query: str, top_k: int = 10) -> List[Document]:\n", - " full_text_search = MongoDBAtlasFullTextSearchRetriever(\n", - " collection=collection,\n", - " search_index_name=TEXT_SEARCH_INDEX,\n", - " search_field=\"text\",\n", - " top_k=top_k\n", - " )\n", - " return full_text_search.get_relevant_documents(query)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "TCaTEr5eBCaL", - "outputId": "07fa1703-0874-4798-bbd5-89c62d9ce9fa" - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - ":13: LangChainDeprecationWarning: The method `BaseRetriever.get_relevant_documents` was deprecated in langchain-core 0.1.46 and will be removed in 1.0. Use :meth:`~invoke` instead.\n", - " return full_text_search.get_relevant_documents(query)\n" - ] - }, - { - "data": { - "text/plain": [ - "[Document(metadata={'_id': '10608397', 'title': 'High-performance neuroprosthetic control by an individual with tetraplegia.', 'embedding': [0.04973480477929115, 0.03962016850709915, 0.039430856704711914, 0.05847017467021942, -0.008748890832066536, -0.015090822242200375, -0.013170663267374039, 0.11856301873922348, 0.07177606225013733, 0.06485266983509064, 0.035752806812524796, -0.035211917012929916, -0.020391540601849556, -0.038754746317863464, 0.09503431618213654, -0.13619601726531982, 0.06528538465499878, -0.10163316875696182, -4.650911796488799e-05, 0.03134455531835556, 0.1062307357788086, -0.06025511026382446, -0.0011722093913704157, -0.03283200412988663, 0.04792282357811928, -0.02377210184931755, 0.008437879383563995, -0.055495280772447586, -0.04043150320649147, 0.01054734829813242, 0.02690926194190979, -0.02799104154109955, -0.09589973837137222, -0.07139743864536285, -0.006781404372304678, 0.022406354546546936, 0.028045129030942917, 0.014374143444001675, -0.02072959765791893, 0.03994470089673996, 0.086001455783844, -0.09708969295024872, 0.0025235884822905064, 0.10974651575088501, -0.055765725672245026, -0.04302777349948883, -0.05495439097285271, 0.004340639803558588, -0.03715911880135536, 0.12548640370368958, -0.03913336619734764, 0.09384436160326004, -0.02708505094051361, 0.06755711883306503, -0.03783523291349411, 0.12018568813800812, 0.016240213066339493, -0.05078953877091408, -0.04805804789066315, 0.04527246579527855, -0.06193186715245247, -0.05400783568620682, 0.056090258061885834, -0.06409543007612228, -0.09243804216384888, 0.020526763051748276, -0.09449342638254166, 0.03840316832065582, 0.005557641386985779, 0.032886091619729996, -0.06571809202432632, 0.06371680647134781, -0.023082466796040535, 0.044569309800863266, -0.10687980055809021, 0.07805038243532181, -0.033913783729076385, 0.06560991704463959, 0.0519254095852375, 0.006835493259131908, -0.05495439097285271, -0.09730605036020279, -0.008863830007612705, 0.007038326933979988, -0.13727779686450958, 0.004482623189687729, -0.05506256967782974, -0.12721724808216095, -0.08562283217906952, -0.06085008755326271, 0.007457516621798277, -0.021513886749744415, -0.046597644686698914, 0.055549368262290955, 0.09005813300609589, -0.1271090805530548, -0.026652337983250618, -0.013799447566270828, 0.050167515873909, 0.0689634308218956, -0.03031686693429947, 0.03710503131151199, 0.03294018283486366, -0.023258255794644356, 0.09844192117452621, 0.021730242297053337, -0.02100004069507122, 0.036564141511917114, 0.05998466536402702, 0.045921534299850464, 0.05619843676686287, -0.029965287074446678, -0.03669936582446098, -0.018295593559741974, 0.09081537276506424, -0.06945023685693741, 0.09470978379249573, -0.08107936382293701, 0.043460484594106674, -0.007890228182077408, -0.03840316832065582, 0.09968596696853638, -0.01898522675037384, -0.10877291113138199, -0.014766287989914417, -0.0935739129781723, 0.008863830007612705, -0.008681279607117176, -0.016551224514842033, -0.1318688988685608, 0.0158480666577816, 0.0950884073972702, 0.10152499377727509, -0.06858480721712112, -0.10568984597921371, 0.09752240777015686, -0.07069428265094757, -0.022135909646749496, -0.07529184222221375, -0.04567813128232956, -0.07610318064689636, -0.03702389821410179, -0.02999233268201351, -0.010811032727360725, -0.07345281541347504, -0.0031320892740041018, 0.14376847445964813, 0.1153176799416542, 0.0016091468278318644, 0.024123679846525192, -0.053980790078639984, 0.0017164795426651835, -0.018511949107050896, 0.03318358212709427, -0.01341406349092722, -0.052899010479450226, -0.08405425399541855, 0.07810446619987488, -0.028937596827745438, -0.12581093609333038, -0.023393478244543076, 0.018457859754562378, 0.06160733476281166, -0.00996589194983244, 0.07312828302383423, 0.14387665688991547, -0.06707032024860382, 0.08735368400812149, -0.10736659914255142, -0.06907161325216293, -0.006142478436231613, -0.06809800863265991, -0.1677839756011963, 0.015293655917048454, 0.03410309553146362, -0.08610963821411133, 0.0851360335946083, 0.011169372126460075, -0.005882175173610449, -0.16215872764587402, -0.08281020820140839, 0.016672924160957336, 0.038619522005319595, 0.08654234558343887, -0.14463390409946442, 0.026408938691020012, -0.07188423722982407, 0.06598854064941406, -0.0415673702955246, 0.003982300404459238, 0.07280375063419342, -2.120773569913581e-05, 0.08740776777267456, 0.03294018283486366, 0.05430532246828079, -0.013035440817475319, 0.1195366159081459, -0.01906636171042919, 0.014306532219052315, -0.10601437836885452, 0.020878341048955917, -0.03134455531835556, 0.009120752103626728, -0.09963187575340271, 0.038835879415273666, -0.034589894115924835, 0.030208688229322433, 0.08021394163370132, -0.014698676764965057, -0.005601588636636734, 0.0018170512048527598, -0.02834261953830719, 0.0746968612074852, -0.01227143406867981, -0.05387261137366295, -0.025908615440130234, 0.00805925577878952, 0.017673570662736893, -0.02530011534690857, -0.026260193437337875, -0.05933559685945511, -0.04143214970827103, 0.031615000218153, 0.06847663223743439, -0.08427061140537262, 0.0054021356627345085, 0.09076128900051117, 0.05373739078640938, 0.029180997982621193, -0.05484621226787567, 0.03934972360730171, -0.003162514418363571, 0.06901752203702927, -0.047706469893455505, 0.01077046524733305, 0.08654234558343887, 0.04397432878613472, -0.01687575876712799, 0.05933559685945511, -0.07085654884576797, 0.10633891075849533, 0.08610963821411133, 0.0718301460146904, -0.05051909387111664, -0.028531929478049278, 0.03139864653348923, -0.05982239916920662, -0.04343344271183014, 0.0023613215889781713, -0.005672580562531948, 0.03780818730592728, -0.028423752635717392, 0.0035259246360510588, 0.011791395023465157, -0.050573185086250305, 0.041702594608068466], 'score': 6.045361518859863}, page_content=\"BACKGROUND Paralysis or amputation of an arm results in the loss of the ability to orient the hand and grasp, manipulate, and carry objects, functions that are essential for activities of daily living. Brain-machine interfaces could provide a solution to restoring many of these lost functions. We therefore tested whether an individual with tetraplegia could rapidly achieve neurological control of a high-performance prosthetic limb using this type of an interface. METHODS We implanted two 96-channel intracortical microelectrodes in the motor cortex of a 52-year-old individual with tetraplegia. Brain-machine-interface training was done for 13 weeks with the goal of controlling an anthropomorphic prosthetic limb with seven degrees of freedom (three-dimensional translation, three-dimensional orientation, one-dimensional grasping). The participant's ability to control the prosthetic limb was assessed with clinical measures of upper limb function. This study is registered with ClinicalTrials.gov, NCT01364480. FINDINGS The participant was able to move the prosthetic limb freely in the three-dimensional workspace on the second day of training. After 13 weeks, robust seven-dimensional movements were performed routinely. Mean success rate on target-based reaching tasks was 91·6% (SD 4·4) versus median chance level 6·2% (95% CI 2·0-15·3). Improvements were seen in completion time (decreased from a mean of 148 s [SD 60] to 112 s [6]) and path efficiency (increased from 0·30 [0·04] to 0·38 [0·02]). The participant was also able to use the prosthetic limb to do skilful and coordinated reach and grasp movements that resulted in clinically significant gains in tests of upper limb function. No adverse events were reported. INTERPRETATION With continued development of neuroprosthetic limbs, individuals with long-term paralysis could recover the natural and intuitive command signals for hand placement, orientation, and reaching, allowing them to perform activities of daily living. FUNDING Defense Advanced Research Projects Agency, National Institutes of Health, Department of Veterans Affairs, and UPMC Rehabilitation Institute.\"),\n", - " Document(metadata={'_id': '40212412', 'title': 'Periosteal bone formation--a neglected determinant of bone strength.', 'embedding': [0.1082371175289154, 0.1280379444360733, 0.1598527580499649, 0.03673721104860306, -0.029200661927461624, 0.13182012736797333, 0.09383145719766617, -0.07575485855340958, 0.017103243619203568, -0.044329386204481125, 0.03173138573765755, -0.04374537244439125, -0.0208993311971426, 0.034067437052726746, 0.04516369104385376, 0.009698791429400444, 0.09772487729787827, -0.0628509446978569, -0.055230963975191116, -0.03242664039134979, 0.044829968363046646, -0.022303743287920952, 0.0075574093498289585, -0.1303739994764328, -0.033956196159124374, 0.0214416291564703, 0.03237101808190346, -0.032927222549915314, -0.0032937650103121996, -0.037905238568782806, 0.01654704101383686, -0.04989141598343849, 0.0054925051517784595, -0.005270024295896292, -0.0731407031416893, 0.043189167976379395, 0.05108725279569626, -0.029089421033859253, 0.10273070633411407, -0.019925974309444427, 0.0005744535010308027, -0.03401181846857071, -0.06435269862413406, 0.028783509507775307, 0.012577141635119915, 0.02053779922425747, -0.009643170982599258, -0.041770849376916885, 0.026072019711136818, 0.1065128892660141, -0.04174304008483887, 0.024584176018834114, 0.07102712988853455, -0.00039064575685188174, -0.033844955265522, 0.0541185587644577, -0.03634786978363991, 0.03403962776064873, -0.027281761169433594, 0.1804322749376297, -0.06618816405534744, -0.06340715289115906, -0.033956196159124374, 0.012883054092526436, -0.07086027413606644, 0.010136800818145275, -0.15473569929599762, 0.031508903950452805, -0.05311739444732666, 0.016449706628918648, -0.06958100199699402, -0.18132220208644867, -0.038683924823999405, 0.0849878266453743, 0.044579677283763885, -0.08648958057165146, -0.003469316754490137, 0.04566427320241928, -0.017881928011775017, 0.03092489019036293, 0.01115882396697998, 0.035096414387226105, -0.10456617921590805, -0.05058667063713074, -0.06351839005947113, -0.052700240164995193, 0.07386376708745956, -0.014558615162968636, -0.13204260170459747, 0.05250557139515877, 0.04502463713288307, -0.09132854640483856, 0.03473488241434097, 0.05481381341814995, 0.014078889973461628, 0.02462589181959629, 0.02500132843852043, 0.034456782042980194, -0.027420811355113983, 0.023916732519865036, -0.007494836580008268, -0.021483343094587326, 0.025599246844649315, -0.11569023877382278, 0.15262211859226227, -0.08621147274971008, 0.006490194704383612, -0.0746980756521225, -0.021080097183585167, -0.0810944065451622, -0.03590290993452072, 0.01231989823281765, -0.06791239231824875, 0.04363413155078888, -0.00911477766931057, -0.04610923305153847, 0.013418398797512054, 0.06324028968811035, 0.0310361310839653, 0.03173138573765755, -0.011687217280268669, 0.11062879115343094, -0.04204895347356796, 0.0007208913448266685, 0.06318467110395432, -0.03860049322247505, 0.04983579367399216, 0.1074584349989891, -0.06807925552129745, -0.08365294337272644, 0.014614235609769821, 0.03904545679688454, 0.04079749435186386, -0.12303212285041809, -0.15228840708732605, 0.007108970545232296, -0.054980672895908356, 0.037543706595897675, 0.06474203616380692, 0.11980614066123962, -0.03723779693245888, 0.023916732519865036, 0.03787742927670479, 0.060514893382787704, 0.045497409999370575, 0.1253681778907776, 0.042660776525735855, 0.07753470540046692, 0.0188691895455122, -0.0015704046236351132, 0.02283213660120964, 0.021094001829624176, -0.030897080898284912, 0.07714536786079407, -0.01252152118831873, -0.04952988401055336, 0.015003577806055546, 0.016505325213074684, -0.02272089570760727, 0.021372102200984955, 0.010880722664296627, -0.012173894792795181, 0.08788008242845535, 0.039712898433208466, -0.020092835649847984, 0.002304766559973359, -0.03632006049156189, -0.06418583542108536, -0.09194036573171616, -0.007995419204235077, 0.054619140923023224, 0.01448909007012844, -0.05283929035067558, 0.0033163607586175203, 0.024820562452077866, -0.009205160662531853, -3.720694439834915e-05, -0.1249232068657875, 0.030897080898284912, -0.08365294337272644, 0.06368525326251984, 0.03815552964806557, 0.01252152118831873, 0.08504345268011093, 0.013814693316817284, 0.10534486174583435, -0.09889290481805801, 0.09182912856340408, 0.021260863170027733, 0.13938449323177338, -0.0029235424008220434, -0.011798457242548466, -0.013654785230755806, -0.07119399309158325, 0.06946976482868195, -0.1191386952996254, 0.08209557086229324, -0.002756681526079774, 0.09316401183605194, 0.05584278702735901, 0.09071671962738037, -0.010171563364565372, -0.0009073062683455646, -0.13604727387428284, 0.013147249817848206, 0.037933047860860825, -0.05662147328257561, 0.056398991495370865, 0.0056732711382210255, -0.038183342665433884, -0.008642004802823067, -0.03595852851867676, 0.07147209346294403, -0.003396315034478903, 0.012007033452391624, -0.01373126357793808, 0.08259615302085876, 0.020217981189489365, -0.07675602287054062, 0.08003762364387512, -0.08098316937685013, -0.0063372389413416386, 0.10095085948705673, 0.16230005025863647, -0.018187839537858963, -0.06479765474796295, 0.07030406594276428, -0.07047092914581299, 0.08103878796100616, -0.005283929407596588, 0.05381264537572861, -0.01835470087826252, 0.06707809120416641, -0.05181031674146652, -0.02708708867430687, -0.011659407056868076, -0.05414636805653572, 0.06318467110395432, 0.08927059173583984, -0.08415352553129196, -0.07987076044082642, 0.016102079302072525, -0.01962006278336048, 0.10389873385429382, -0.03153671324253082, 0.07186143845319748, -0.10829273611307144, 0.01732572540640831, 0.09816984087228775, 0.03423430025577545, 0.03192605450749397, -0.04872338846325874, 0.017603827640414238, -0.03242664039134979, -0.010373187251389027, 0.00214833440259099], 'score': 4.411067962646484}, page_content=\"Life forms that have low body mass can hunt for food on the undersurface of branches or along shear cliff faces quite unperturbed by gravity. For larger animals, the hunt for dinner and the struggle to avoid becoming someone else's meal require rapid movement against gravity. This need is met by the lever function of long bones, three-dimensional masterpieces of biomechanical engineering that, by their material composition and structural design, achieve the contradictory properties of stiffness and flexibility, strength and lightness.1 Material stiffness results from the encrusting of the triple-helical structure of collagen type I with hydroxyapatite crystals, which confers . . .\"),\n", - " Document(metadata={'_id': '43385013', 'title': 'Epithelial and mesenchymal subpopulations within normal basal breast cell lines exhibit distinct stem cell/progenitor properties.', 'embedding': [0.023725250735878944, 0.03393925726413727, 0.12911297380924225, 0.07809252291917801, 0.014056653715670109, 0.019461151212453842, 0.08810819685459137, -0.016610154882073402, -0.029154540970921516, -0.018308358266949654, 0.005516058765351772, -0.05082211643457413, 0.035327568650245667, -0.00568030122667551, -0.008410440757870674, 0.10481751710176468, 0.01672171615064144, -0.04380618408322334, 0.004143242258578539, 0.09405810385942459, 0.09509933739900589, -0.0219526756554842, -0.044525131583213806, -0.07075430452823639, -0.10927994549274445, -0.003600932890549302, -0.00010575028863968328, -0.06703560799360275, -0.015234239399433136, 0.04229391738772392, 0.12177474796772003, -0.0356498546898365, -0.012637353502213955, 0.08186079561710358, -0.12772466242313385, 0.0829516127705574, 0.026774577796459198, -0.006526303477585316, 0.023018701002001762, -0.05030149966478348, 0.015321008861064911, -0.014651644043624401, -0.02620437927544117, -0.010418534278869629, 0.0044872211292386055, -0.04345910623669624, -0.08007582277059555, -0.048367779701948166, -0.004741331562399864, 0.11225490272045135, 0.014577270485460758, 0.012042362242937088, 0.04477304592728615, 0.004586386028677225, -0.1241547092795372, -0.004831199999898672, -0.05171460285782814, -0.0645069032907486, -0.07605963945388794, -0.01336249802261591, 0.024940023198723793, 0.009662399999797344, 0.059598229825496674, -0.04717779904603958, -0.02113456279039383, 0.01899011805653572, -0.13238541781902313, -0.06797768175601959, 0.059895724058151245, -0.001645520911552012, 0.005041925702244043, -0.11641983687877655, -0.010368951596319675, 0.04093039780855179, 0.0046266717836260796, -0.029997443780303, 0.05597870051860809, 0.13278207182884216, -0.11661816388368607, -0.02667541243135929, 0.09455392509698868, 0.037657950073480606, 0.03056764416396618, -0.008769913576543331, -0.050450246781110764, 0.015271426178514957, 0.002513215644285083, -0.09009149670600891, -0.11770898103713989, 0.007102700881659985, -0.02667541243135929, -0.037533991038799286, -0.0039975931867957115, 0.10342920571565628, 0.07209303230047226, 0.09450434893369675, 0.01718035526573658, -0.1742330938577652, 0.025175541639328003, 0.029427245259284973, 0.046681974083185196, 0.027741437777876854, -0.03540194407105446, -0.11403986811637878, -0.011918406002223492, 0.006296984385699034, -0.10382586717605591, -0.05107003077864647, -0.04995442181825638, 0.028584342449903488, 0.1998176872730255, -0.009067409671843052, 0.06534980237483978, 0.0669364482164383, 0.048590902239084244, -0.044054098427295685, -0.1306004375219345, 0.017725761979818344, -0.006321775261312723, 0.09490100294351578, -0.007350613363087177, 0.1059083342552185, -0.06331691890954971, -0.0445995070040226, 0.03396404907107353, -0.07834043353796005, 0.1299062818288803, 0.10481751710176468, -0.09405810385942459, -0.08686862885951996, -0.020018955692648888, -0.015011117793619633, 0.045045748353004456, -0.01735389418900013, -0.13575702905654907, -0.0363440103828907, 0.001086942502297461, 0.022745996713638306, -0.018531478941440582, 0.036071307957172394, 0.008714133873581886, -0.011106492020189762, 0.0525079220533371, -0.004849793389439583, -0.03862480819225311, -0.03993874788284302, -0.0891990140080452, 0.07938166707754135, -0.014775600284337997, 0.10600749403238297, -0.02475409023463726, 0.038228146731853485, 0.07318384945392609, -0.01018921472132206, -0.007951801642775536, 0.0008769914275035262, 0.054193731397390366, 0.03996353596448898, -0.06772976368665695, -0.081563301384449, -0.0414758063852787, 0.078241266310215, -0.07184512168169022, -0.013003024272620678, -0.0407816506922245, 0.03812898322939873, -0.021642783656716347, -0.048690065741539, -0.17681138217449188, -0.049235474318265915, -0.003889131359755993, 0.004580188076943159, -0.03983958065509796, -0.08463741838932037, -0.21340329945087433, -0.06282109767198563, -0.0695643201470375, -0.09063690900802612, -0.022027049213647842, 0.008838090114295483, 0.05374748632311821, 0.09509933739900589, 0.04891318827867508, 0.04747529327869415, 0.04826861619949341, 0.06153194606304169, -0.0306915994733572, 0.08622405678033829, 0.03924459218978882, -0.04393014311790466, -0.02258485183119774, -0.03098909556865692, 0.0021181046031415462, 0.046731557697057724, 0.007220459170639515, 0.007610921747982502, 0.17165479063987732, 0.1135440468788147, 0.03664150461554527, 0.06901891529560089, 0.0898931697010994, -0.023725250735878944, 0.05642494559288025, -0.037583574652671814, -0.002869590185582638, 0.04122789204120636, -0.04762404039502144, 0.02940245345234871, -0.03535236045718193, 0.03379051014780998, 0.06718435883522034, 0.11275072395801544, -0.013907905668020248, 0.08354660123586655, -0.03448466584086418, 0.07139887660741806, 0.005082211457192898, 0.00738160265609622, 0.05201209709048271, 0.03629442676901817, 0.02184111438691616, -0.08265411853790283, 0.08518282324075699, 0.09792554378509521, -0.012686935253441334, -0.057267848402261734, -0.01990739442408085, -0.07293593138456345, -0.07710087299346924, 0.016498593613505363, 0.008831892162561417, 0.04442596808075905, 0.007009733468294144, -0.029551200568675995, -0.017081189900636673, 0.008131538517773151, -0.05766450986266136, -0.011391591280698776, 0.07640671730041504, -0.029328079894185066, -0.03004702739417553, 0.08062122762203217, 0.03056764416396618, 0.004171132110059261, 0.04866527393460274, 0.07898500561714172, -0.036715880036354065, -0.06857267022132874, -0.04122789204120636, -0.015147469937801361, -0.04581427946686745, 0.07551422715187073, 0.03143533691763878, -0.005227860528975725, -0.06019321829080582, 0.019064491614699364], 'score': 4.344019412994385}, page_content='It has been proposed that epithelial-mesenchymal transition (EMT) in mammary epithelial cells and breast cancer cells generates stem cell features, and that the presence of EMT characteristics in claudin-low breast tumors reveals their origin in basal stem cells. It remains to be determined, however, whether EMT is an inherent property of normal basal stem cells, and if the presence of a mesenchymal-like phenotype is required for the maintenance of all their stem cell properties. We used nontumorigenic basal cell lines as models of normal stem cells/progenitors and demonstrate that these cell lines contain an epithelial subpopulation (\"EpCAM+,\" epithelial cell adhesion molecule positive [EpCAM(pos)]/CD49f(high)) that spontaneously generates mesenchymal-like cells (\"Fibros,\" EpCAM(neg)/CD49f(med/low)) through EMT. Importantly, stem cell/progenitor properties such as regenerative potential, high aldehyde dehydrogenase 1 activity, and formation of three-dimensional acini-like structures predominantly reside within EpCAM+ cells, while Fibros exhibit invasive behavior and mammosphere-forming ability. A gene expression profiling meta-analysis established that EpCAM+ cells show a luminal progenitor-like expression pattern, while Fibros most closely resemble stromal fibroblasts but not stem cells. Moreover, Fibros exhibit partial myoepithelial traits and strong similarities with claudin-low breast cancer cells. Finally, we demonstrate that Slug and Zeb1 EMT-inducers control the progenitor and mesenchymal-like phenotype in EpCAM+ cells and Fibros, respectively, by inhibiting luminal differentiation. In conclusion, nontumorigenic basal cell lines have intrinsic capacity for EMT, but a mesenchymal-like phenotype does not correlate with the acquisition of global stem cell/progenitor features. Based on our findings, we propose that EMT in normal basal cells and claudin-low breast cancers reflects aberrant/incomplete myoepithelial differentiation.'),\n", - " Document(metadata={'_id': '10931595', 'title': 'Geometry, epistasis, and developmental patterning.', 'embedding': [0.0491923987865448, 0.05855976790189743, 0.12226885557174683, 0.09674139320850372, 0.0009851831709966063, 0.04300226271152496, 0.13486824929714203, -0.06425688415765762, -0.04122191295027733, 0.09455019980669022, 0.07723972946405411, -0.03651083633303642, 0.0463438406586647, -0.012647321447730064, 0.03412790969014168, -0.07636325061321259, 0.09811089187860489, 0.001799179008230567, -0.010462970472872257, 0.11142241954803467, 0.08271772414445877, -0.0002925163717009127, 0.02873208560049534, 0.05861454829573631, 0.0058135222643613815, -0.007326818536967039, 0.10638266801834106, 0.12303577363491058, 0.055108632892370224, -0.023418430238962173, 0.15305519104003906, -0.03514133766293526, -0.05620422959327698, -0.0005717657622881234, -0.1791304498910904, 0.06568115949630737, 0.04689163714647293, 0.06650286167860031, -0.008614147081971169, 0.09975429624319077, 0.012647321447730064, -0.02708868682384491, -0.14111316204071045, 0.06064140796661377, -0.08907220512628555, -0.015352081507444382, -0.06354474276304245, 0.025773966684937477, 0.0129280686378479, 0.06765323877334595, -0.037825558334589005, -0.0019857732113450766, 0.10643744468688965, 0.05812152847647667, -0.11470922082662582, 0.012010504491627216, -0.02544528804719448, -0.06650286167860031, -0.051986172795295715, -0.023185614496469498, 0.002949557965621352, -0.061189208179712296, 0.0013737784465774894, 0.034894827753305435, 0.040537163615226746, 0.00023281479661818594, -0.0583406500518322, -0.023897754028439522, 0.005751894786953926, 0.03670256957411766, 0.0245961993932724, -0.08759314566850662, 0.06962531805038452, 0.038428135216236115, 0.047603778541088104, -0.007819837890565395, -0.01333891786634922, 0.15930010378360748, -0.005632063839584589, 0.026540886610746384, 0.09641271829605103, -0.022131100296974182, 0.06672198325395584, -0.0807456523180008, -0.07340513914823532, -0.027882995083928108, 0.015653371810913086, -0.07187129557132721, -0.16927005350589752, -0.0331144817173481, 0.02096702717244625, -0.05089057609438896, -0.11186066269874573, 0.07795187085866928, 0.06162744760513306, 0.04974019527435303, 0.010120595805346966, -0.03829118609428406, 0.0797596126794815, -0.04048238322138786, 0.034675709903240204, -0.023829279467463493, 0.005549893714487553, -0.051986172795295715, 0.05916234850883484, -0.013058170676231384, -0.11470922082662582, 0.0668315440416336, 0.014516687020659447, -0.006036065984517336, 0.08666188269853592, 0.011175110004842281, -0.0023914873600006104, 0.04341311380267143, -0.024842707440257072, -0.13103364408016205, -0.1573280245065689, -0.034894827753305435, 0.04853503778576851, 0.07477463781833649, -0.027157161384820938, 0.0228569358587265, 0.009545406326651573, 0.023322565481066704, 0.1053418442606926, 0.0062551856972277164, -0.05773806944489479, -0.017050260677933693, -0.003974970430135727, -0.02387036383152008, -0.00985354371368885, 0.06962531805038452, -0.008874352090060711, -0.034073129296302795, -0.14023667573928833, -0.03788033500313759, -0.003509340574964881, 0.12533652782440186, -0.021240927278995514, 0.032429732382297516, -0.012325488962233067, 0.06595506519079208, 0.03462092950940132, -0.036127377301454544, -0.009107166901230812, 0.07477463781833649, -0.0038209017366170883, 0.07395293563604355, -0.06770802289247513, 0.11361362040042877, -0.02232282981276512, 0.026472412049770355, 0.04437176138162613, -0.0665576383471489, -0.012037894688546658, -0.08710012584924698, -0.07384337484836578, 0.0362643264234066, -0.05642335116863251, 0.015721846371889114, -0.05850498750805855, 0.04771333932876587, 0.029964633285999298, 0.09098950028419495, -0.06294216215610504, 0.11722909659147263, -0.09953517466783524, -0.0014987452886998653, -0.08080042898654938, 0.031087622046470642, 0.027294110506772995, -0.0012684982502833009, -0.07619891315698624, -0.0728573352098465, -0.042618803679943085, -0.06502380222082138, -0.09816567599773407, -0.11755777895450592, -0.08425156772136688, -0.12270709127187729, -0.001509016496129334, 0.05590293928980827, -0.06710544228553772, -0.01939210295677185, 0.04204361140727997, 0.04598776996135712, 0.03966068476438522, 0.07022789865732193, -0.011928334832191467, -0.04108496382832527, -0.013332070782780647, 0.038674645125865936, 0.13946975767612457, 0.02604786679148674, 0.04371440038084984, -0.031553253531455994, 0.11071028560400009, 0.006289423443377018, 0.08836006373167038, -0.10709480941295624, 0.050123654305934906, 0.011209347285330296, 0.07828055322170258, -0.06896796077489853, -0.0463438406586647, 0.011209347285330296, -0.06989921629428864, -0.05163010582327843, -0.033634889870882034, 0.06140832602977753, 0.03924983739852905, -0.0782257691025734, -0.02834862470626831, 0.03938678652048111, -0.037414707243442535, -0.0020679431036114693, -0.0800882875919342, -0.0012308370787650347, 0.0334157720208168, 0.012188538908958435, -0.04127669334411621, 0.019337322562932968, 0.021391570568084717, 0.033881399780511856, -0.06343518197536469, -0.004341311287134886, 0.03683951869606972, -0.0435226708650589, -0.03308708965778351, 0.010106900706887245, 0.03560696914792061, 0.07723972946405411, 0.011757147498428822, 0.0030128974467515945, -0.06124398484826088, 0.04018109664320946, -0.03670256957411766, 0.026294376701116562, 0.01105185505002737, -0.05168488621711731, -0.03725036606192589, 0.05538253113627434, -0.04938412830233574, 0.06518813967704773, -0.03081372380256653, 0.08463502675294876, -0.029307274147868156, -0.057409390807151794, -0.15710890293121338, -0.07351469248533249, -0.005056874360889196, 0.05631379038095474, 0.06376386433839798, 0.022473474964499474, -0.029690733179450035, -0.011031312867999077], 'score': 4.270141124725342}, page_content='Developmental signaling networks are composed of dozens of components whose interactions are very difficult to quantify in an embryo. Geometric reasoning enumerates a discrete hierarchy of phenotypic models with a few composite variables whose parameters may be defined by in vivo data. Vulval development in the nematode Caenorhabditis elegans is a classic model for the integration of two signaling pathways; induction by EGF and lateral signaling through Notch. Existing data for the relative probabilities of the three possible terminal cell types in diverse genetic backgrounds as well as timed ablation of the inductive signal favor one geometric model and suffice to fit most of its parameters. The model is fully dynamic and encompasses both signaling and commitment. It then predicts the correlated cell fate probabilities for a cross between any two backgrounds/conditions. The two signaling pathways are combined additively, without interactions, and epistasis only arises from the nonlinear dynamical flow in the landscape defined by the geometric model. In this way, the model quantitatively fits genetic experiments purporting to show mutual pathway repression. The model quantifies the contributions of extrinsic vs. intrinsic sources of noise in the penetrance of mutant phenotypes in signaling hypomorphs and explains available experiments with no additional parameters. Data for anchor cell ablation fix the parameters needed to define Notch autocrine signaling.'),\n", - " Document(metadata={'_id': '27049238', 'title': 'Large deformation of red blood cell ghosts in a simple shear flow.', 'embedding': [0.05452635511755943, 0.04289012402296066, 0.15307152271270752, 0.14737433195114136, -0.0037488548550754786, -0.009466194547712803, -0.005717339459806681, -0.004434129223227501, -0.02102852240204811, -0.01877114735543728, 0.011300311423838139, -0.0030518232379108667, -0.1063116118311882, 0.060572896152734756, 0.0384022481739521, 0.10840774327516556, 0.05863800272345543, -0.028002198785543442, -0.04452940821647644, 0.03399499133229256, 0.06422769278287888, 0.004235937260091305, 0.025005802512168884, 0.11018139868974686, -0.010796433314681053, -0.013356135226786137, 0.10389299690723419, 0.037703536450862885, 0.01842179149389267, -0.10480669140815735, 0.05933671444654465, -0.05011909827589989, 0.05084468424320221, -0.06304525583982468, -0.058799244463443756, 0.13544249534606934, -0.016030048951506615, 0.1063116118311882, -0.055789411067962646, -0.0007440603221766651, 0.06530263274908066, 0.020356684923171997, -0.011804189532995224, 0.12146827578544617, 0.012166982516646385, 0.03160325065255165, -0.012200574390590191, -0.05350515991449356, 0.03665547072887421, 0.09636840969324112, -0.036951079964637756, 0.036279238760471344, 0.03848286718130112, -0.00543516781181097, -0.10975141823291779, -0.0017434190958738327, -0.01842179149389267, 0.046141818165779114, -0.03945031389594078, -0.05557442083954811, -0.03595675900578499, -0.013154583983123302, -0.10545165836811066, -0.02308434620499611, -0.027088498696684837, 0.006389177404344082, -0.18574970960617065, -0.01831429824233055, 0.015371648594737053, 0.07959934324026108, -0.023662127554416656, -0.04057900235056877, -0.015317901968955994, -0.036870457231998444, -0.09077872335910797, -0.060626640915870667, 0.024495204910635948, 0.03649422898888588, 0.014310144819319248, 0.08723141998052597, 0.04834544658660889, -0.09228363633155823, 0.038348499685525894, -0.014242961071431637, -0.049044158309698105, -0.022036278620362282, 0.10760153830051422, -0.02581200748682022, -0.07191351801156998, -0.018878642469644547, -0.027478165924549103, 0.049527883529663086, -0.07169853150844574, -0.0010589843150228262, -0.07922311127185822, 0.058208025991916656, -0.04735112562775612, -0.06637757271528244, 0.041895803064107895, 0.017803700640797615, 0.04111647233366966, 0.03678983822464943, -0.0250998605042696, 0.03455933555960655, 0.058208025991916656, -0.040122151374816895, -0.03359188884496689, -0.01877114735543728, 0.009728210978209972, -0.002736059483140707, 0.1754302829504013, -0.07368716597557068, 0.02645697258412838, -0.0478348508477211, 0.09072497487068176, -0.06997862458229065, -0.07761070132255554, -0.0009069810039363801, -0.10894521325826645, 0.03058205544948578, -0.012059488333761692, 0.008324069902300835, 0.08099676668643951, -0.017199046909809113, 0.08056678622961044, -0.05992792919278145, 0.054902583360672, -0.07809442281723022, -0.08793012797832489, -0.04834544658660889, 0.0041485982947051525, -0.008995908312499523, 0.018059000372886658, -0.13318511843681335, -0.0933048352599144, 0.0006290081073530018, 0.02875465713441372, 0.07411714643239975, 0.09255237132310867, -0.03872473165392876, 0.0069803944788873196, 0.06573260575532913, 0.10706406831741333, 7.762875611661002e-05, -0.01225432101637125, 0.0762132778763771, -0.014068283140659332, 0.07814817130565643, 0.021458499133586884, 0.043427594006061554, -0.011051731184124947, 0.08637146651744843, 0.020826971158385277, 0.011851218529045582, 0.019348928704857826, -0.064980149269104, 0.11050388216972351, -0.0034095768351107836, -0.004773407708853483, 0.04498625919222832, -0.0703011080622673, -0.02179441787302494, -0.07363342493772507, -0.10727905482053757, -0.11050388216972351, 0.020679166540503502, -0.032167594879865646, -0.03335002809762955, -0.04627618566155434, 0.019335491582751274, 0.04286324977874756, -0.03171074390411377, -0.08723141998052597, -0.08991876989603043, -0.020504489541053772, 0.050468456000089645, 0.0206657312810421, -0.09712087363004684, 0.01800525188446045, 0.08465155959129333, 0.038885969668626785, 0.032167594879865646, -0.0286471638828516, 0.006795639172196388, -0.03348439559340477, 0.07212850451469421, 0.08948879688978195, 0.08260917663574219, -0.001447810442186892, -0.027625970542430878, -0.08492029458284378, 0.060196664184331894, 0.03372625634074211, -0.08400660008192062, -0.11233127862215042, -0.07056984305381775, 0.06815122812986374, 0.0011312068672850728, -0.02604043297469616, -0.04740487411618233, 0.1174909919500351, -0.004995114170014858, 0.05345141515135765, -0.14318206906318665, -0.05275270342826843, 0.001909698941744864, -0.06401270627975464, 0.038348499685525894, 0.0277603380382061, 0.04976974427700043, 0.09975447505712509, 0.03052830882370472, -0.03087766468524933, 0.02402491867542267, -0.0419495515525341, -0.09932450205087662, 0.02551640011370182, 0.06691504269838333, -0.001196711091324687, 0.019120503216981888, -0.07218225300312042, 0.0602504126727581, 0.18295486271381378, 0.14952421188354492, -0.1494167298078537, -0.014175777323544025, 0.12480058521032333, 0.008848103694617748, -0.10222683846950531, 0.022708117961883545, 0.043669454753398895, -0.0037454955745488405, 0.0010312709491699934, 0.008230012841522694, -0.0014637665590271354, -0.013530813157558441, -0.06637757271528244, 0.05568191409111023, -0.0011228088987991214, -0.08744640648365021, -0.055843155831098557, 0.07309595495462418, -0.022170646116137505, -0.11082635819911957, -0.02491174452006817, 0.02958773635327816, -0.05232272669672966, -0.05089842900633812, 0.09088621288537979, -0.014189214445650578, -0.04702864587306976, -0.010762841440737247, 0.06858120113611221, -0.05393513664603233, -0.03920845314860344, 0.0036010504700243473], 'score': 4.082460880279541}, page_content='Red blood cells are known to change shape in response to local flow conditions. Deformability affects red blood cell physiological function and the hydrodynamic properties of blood. The immersed boundary method is used to simulate three-dimensional membrane-fluid flow interactions for cells with the same internal and external fluid viscosities. The method has been validated for small deformations of an initially spherical capsule in simple shear flow for both neo-Hookean and the Evans-Skalak membrane models. Initially oblate spheroidal capsules are simulated and it is shown that the red blood cell membrane exhibits asymptotic behavior as the ratio of the dilation modulus to the extensional modulus is increased and a good approximation of local area conservation is obtained. Tank treading behavior is observed and its period calculated.'),\n", - " Document(metadata={'_id': '95764370', 'title': 'Modification in the chemical bath deposition apparatus, growth and characterization of CdS semiconducting thin films for photovoltaic applications', 'embedding': [0.035667359828948975, -0.017749670892953873, 0.037035487592220306, 0.08981645852327347, 0.006480610463768244, 0.05136483907699585, -0.012877212837338448, -0.1198192834854126, 0.05976562947034836, -0.10004141926765442, 0.055493228137493134, -0.04894061014056206, -0.09236069768667221, -0.03890766575932503, 0.12874813377857208, 0.08501600474119186, -0.03938771039247513, 0.03249906003475189, 0.013453267514705658, -0.013885308057069778, 0.05899755656719208, 0.03876364976167679, -0.026618506759405136, 0.011263060383498669, -0.04015578329563141, -0.09048852324485779, 0.1407492607831955, 0.020845962688326836, 0.07762330770492554, -0.05885354429483414, -0.0011761108180508018, -0.06259789317846298, -0.046972423791885376, -0.03998776525259018, -0.15092621743679047, 0.11597892642021179, 0.034491248428821564, 0.020773956552147865, -0.0627899169921875, -0.03300310671329498, 0.036315418779850006, 0.00783073715865612, -0.025010354816913605, 0.011695101857185364, -0.06576619297266006, 0.010338974185287952, -0.09341679513454437, 0.10052146762609482, 0.04853257164359093, 0.012721198610961437, -0.08568806946277618, 0.06043769419193268, 0.07603916525840759, -0.05126882717013359, 0.028034640476107597, -0.03269108012318611, -0.055925268679857254, 0.022946162149310112, -0.013741293922066689, -0.046804409474134445, 0.05011672154068947, -0.07757530361413956, -0.024674324318766594, -0.0016486552776768804, -0.04930064454674721, -0.03185100108385086, -0.013345257379114628, 0.05405309051275253, 0.08151167631149292, -0.026642508804798126, 0.06019767001271248, 0.04229198396205902, 0.0038643640000373125, 0.07301487773656845, -0.057173386216163635, 0.0043534100987017155, 0.0037863566540181637, -0.035643357783555984, -0.017089609056711197, 0.08957643806934357, -0.004590432159602642, -0.047308456152677536, -0.05112481489777565, -0.025826431810855865, -0.03974774479866028, -0.07018261402845383, 0.12711597979068756, 0.0018616752931848168, -0.11530686169862747, -0.001717661740258336, 0.011089044623076916, 0.03218703344464302, -0.08386389911174774, 0.036867473274469376, -0.04915662854909897, -0.04322807118296623, -0.03317112475633621, -0.028538687154650688, -0.006684629712253809, 0.09116058796644211, 0.055493228137493134, 0.03398720175027847, 0.005010472144931555, -0.02909073978662491, 0.045844316482543945, 0.011473081074655056, -0.044980235397815704, -0.013009225018322468, 0.011839115060865879, -0.05477315932512283, 0.17281627655029297, -0.01688558980822563, 0.08031156659126282, 0.06307794153690338, 0.014221339486539364, -0.019429830834269524, -0.03115493431687355, 0.014713386073708534, -0.0750790685415268, 0.12769202888011932, -0.09346480667591095, 0.11722704023122787, 0.06725433468818665, -0.024362294003367424, 0.0789194330573082, -0.008004753850400448, -0.015229434706270695, -0.13921311497688293, -0.044140156358480453, 0.03468326851725578, 0.020821960642933846, -0.011209055781364441, 0.05203690007328987, -0.18174511194229126, -0.05952560529112816, -0.12231551855802536, 0.035835374146699905, 0.006348597817122936, 0.035355329513549805, -0.0046984427608549595, 0.11261861026287079, 0.06211785227060318, 0.11261861026287079, 0.09740117192268372, -0.054581139236688614, -0.07099868357181549, 0.044812221080064774, -0.011785110458731651, -0.044860225170850754, 0.06576619297266006, -0.0603896863758564, 0.04934864863753319, 0.09917733818292618, -0.05045275017619133, 0.011557088233530521, -0.01455737091600895, -0.019285816699266434, 0.07594314962625504, -0.035787370055913925, 0.09610505402088165, 0.05328501760959625, 0.02133801020681858, 0.0016801581950858235, -0.0654301643371582, -0.03285909444093704, -0.036939479410648346, 0.001304372912272811, 0.035763368010520935, -0.06307794153690338, 0.028850717470049858, 0.05347703769803047, -0.08856834471225739, 0.03348315507173538, -0.001587149454280734, -0.05155685544013977, -0.022502118721604347, 0.012961220927536488, -0.06499812006950378, -0.08794428408145905, 0.012553182430565357, 0.04831654950976372, -0.011695101857185364, -0.06912650913000107, -0.10426582396030426, 0.009624906815588474, -0.12202749401330948, -0.03782756254076958, 0.036651451140642166, 0.007554711773991585, -0.055877264589071274, -0.03281109035015106, -0.05078878253698349, 0.057317398488521576, -0.015625471249222755, -0.056597329676151276, -0.008736822754144669, 0.09370482712984085, 0.11722704023122787, -0.002305717207491398, -0.07047063857316971, -0.014761390164494514, 0.004653438460081816, -0.03062688559293747, 0.11002635955810547, -0.07992752641439438, -0.046300359070301056, -0.12154744565486908, -0.03089090995490551, 0.06840644031763077, -0.06034168228507042, 0.03276308625936508, 0.09634507447481155, -0.058037467300891876, -0.004578431136906147, -0.03785156458616257, 0.024554312229156494, -0.004920463543385267, -0.03348315507173538, 0.04238799214363098, 0.007710726466029882, -0.05184488371014595, 0.021686041727662086, 0.036915477365255356, -0.00846679788082838, -0.005127483047544956, 0.07618317753076553, -0.1164589673280716, 0.027002543210983276, 0.05434111878275871, -0.1445896178483963, -0.00472244480624795, 0.022658133879303932, -0.08410391956567764, 0.0998494029045105, -0.02213008515536785, -0.009354881010949612, 0.026162464171648026, 0.09135260432958603, -0.10935430228710175, -0.05338102951645851, -0.0844399556517601, -0.017989695072174072, -0.008070760406553745, 0.07647120207548141, -0.0377795584499836, 0.08520802855491638, -0.03885966166853905, -0.10340174287557602, 0.00032440555514767766, 0.05904556065797806, -0.13066831231117249, -0.03386719152331352, -0.09226468950510025, -0.11473080515861511, -0.09111258387565613, -0.09567300975322723], 'score': 3.966486930847168}, page_content='Abstract In this paper, growth and characterization of CdS thin films by Chemical Bath Deposition (CBD) technique using the reaction between CdCl 2 , (NH 2 ) 2 CS and NH 3 in an aqueous solution has been reported. The parameters actively involved in the process of deposition have been identified. A commonly available CBD system has been sucessfully modified to obtain the precious control over the pH of the solution at 90°C during the deposition and studies have been made to understand the fundamental parameters like concentrations of the solution, pH and temperature of the solution involved in the chemical bath deposition of CdS. It is confirmed that the pH of the solution plays a vital role in the quality of the CBD–CdS films. Structural, optical and electrical properties have been analysed for the as-deposited and annealed films. XRD studies on the CBD–CdS films reveal that the change in Cadmium ion concentration in the bath results in the change in crystallization from cubic phase with (1 1 1) predominant orientation to a hexagonal phase with (0 0 2) predominant orientation. The structural changes due to varying cadmium ion concentration in the bath affects the optical and electrical properties. Optimum electrical resistivity, band gap and refractive index value are observed for the annealed films deposited from 0.8 M cadmium ion concentration. The films are suitable for solar cell fabrication. Further on, annealing the samples at 350°C in H 2 for 30 min resulted in an increased diffraction intensity as well as shifts in the peak towards lower scattering angles due to enlarged CdS unit cell. This in turn brought about an increase in the lattice parameters and narrowing in the band-gap values. The results are compared with the analysis of previous work.'),\n", - " Document(metadata={'_id': '803312', 'title': 'Cerebral organoids model human brain development and microcephaly', 'embedding': [0.011010420508682728, -0.014564870856702328, 0.06692420691251755, 0.1460077464580536, -0.06117963790893555, -0.10455112159252167, 0.038536470383405685, 0.06668484956026077, -0.01862197183072567, -0.029010063037276268, 0.03166692703962326, -0.06826460361480713, 0.023253528401255608, -0.11192331463098526, -0.0015618042089045048, -0.07362619787454605, 0.012626079842448235, -0.07668997347354889, 0.06558381021022797, 0.08851420134305954, 0.08253028243780136, 0.01463667768985033, 0.01928020268678665, 0.020201727747917175, 0.06701994687318802, 0.010441947728395462, 0.026065973564982414, -0.004093003924936056, 0.009861506521701813, 0.037196069955825806, 0.030948854982852936, -0.03463495150208473, 0.005340652074664831, 0.030350463464856148, -0.10435963422060013, 0.014421257190406322, 0.0683603510260582, 0.051701102405786514, -0.08339196443557739, 0.1357632726430893, 0.09033332020044327, -0.06338172405958176, 0.12322096526622772, 0.11010420322418213, -0.05198833346366882, 0.042078953236341476, -0.10388091951608658, -0.021362608298659325, -0.0616583526134491, 0.12389115989208221, -0.03657374531030655, 0.030733434483408928, 0.06007859855890274, 0.022894492372870445, -0.0929662436246872, 0.04483155906200409, -0.01707811839878559, -0.016754986718297005, -0.07262089848518372, -0.011471182107925415, 0.03391687944531441, -0.0036382258404046297, 0.10589151829481125, 0.056392498314380646, 0.004006237257272005, -0.02640107274055481, -0.09066841751337051, -0.10426389425992966, 0.10052992403507233, 0.04195927456021309, -0.056871213018894196, -0.049786247313022614, -0.02697552926838398, -0.04796713590621948, 0.05270640179514885, -0.04653099179267883, 0.028100507333874702, 0.05442977324128151, 0.09095564484596252, 0.11747639626264572, 0.044687945395708084, -0.03592747822403908, 0.10455112159252167, -0.05969562754034996, -0.015809526666998863, -0.0036591694224625826, 0.03587960824370384, 0.031427569687366486, -0.07769527286291122, -0.021147187799215317, -0.027095207944512367, -0.056966956704854965, -0.03410836681723595, 0.09713105112314224, 0.027286693453788757, -0.056871213018894196, -0.005119246896356344, -0.09909377992153168, 0.1312633603811264, 0.10780637711286545, -0.024534087628126144, -0.012865436263382435, -0.03942209109663963, 0.031714797019958496, 0.005241917446255684, 0.07549318671226501, -0.0073003871366381645, -0.013080857694149017, -0.035759929567575455, 0.06323810666799545, 0.1440928876399994, -0.020177790895104408, 0.02295433171093464, 0.0033420214895159006, 0.04645918682217598, -0.011309616267681122, -0.09210456162691116, -0.028531350195407867, -0.0010688784532248974, 0.028052635490894318, 0.017736351117491722, 0.06117963790893555, 0.08099839836359024, -0.04748842120170593, 0.04873307794332504, -0.07429639995098114, 0.07003584504127502, 0.040164098143577576, 0.03312700241804123, -0.05825948342680931, -0.002552143530920148, 0.056966956704854965, -0.04174385219812393, -0.07544531673192978, -0.12465710192918777, 0.043539032340049744, -0.09861506521701813, 0.07147198915481567, -0.017508961260318756, -0.0969395712018013, -0.00879038404673338, 0.00045216025318950415, 0.08798761665821075, -0.05280214548110962, 0.01658743806183338, 0.03504185751080513, 0.020225662738084793, 0.11240202933549881, -0.14131635427474976, 0.13921000063419342, 0.005241917446255684, 0.018071450293064117, 0.04997773468494415, -0.04502304270863533, -0.055530816316604614, 0.07132837176322937, 0.07003584504127502, 0.06678058952093124, -0.07305174320936203, -0.09928526729345322, 0.018574099987745285, 0.03516153618693352, -0.01959136687219143, 0.0037938079331070185, -0.08578553795814514, 0.0980406105518341, -0.07372194528579712, 0.009939298033714294, -0.08779612928628922, -0.043156061321496964, -0.04835010692477226, -0.016180530190467834, -0.13040167093276978, 0.008951949886977673, -0.07017946243286133, 0.03765084967017174, -0.04959476366639137, 0.019603334367275238, -0.0023397142067551613, -0.056488242000341415, 0.052084073424339294, 0.08339196443557739, -0.06496147811412811, 0.10876379907131195, 0.04277309030294418, 0.015630008652806282, -0.10416814684867859, -0.054669130593538284, 0.008700625039637089, -0.013356118462979794, -0.016443822532892227, -0.14074189960956573, 0.058403097093105316, 0.053711701184511185, 0.07089753448963165, -0.03252860903739929, 0.10512557625770569, 0.034299854189157486, 0.023959631100296974, -0.06826460361480713, 0.04107365384697914, 0.028818577527999878, -0.025371838361024857, -0.0894237607717514, 0.09267901629209518, 0.06132325157523155, 0.03324668109416962, 0.057828642427921295, 0.02879464253783226, 0.10388091951608658, 0.07597190141677856, -0.01650366187095642, 0.01774831861257553, 0.08401429653167725, -0.030015362426638603, -0.11948699504137039, -0.06156260892748833, -0.026736171916127205, -0.006731914356350899, -0.0014174419920891523, -0.007072998210787773, 0.01382286474108696, 0.04437677934765816, 0.06400404870510101, 0.014612742699682713, -0.03310306742787361, -0.028435606509447098, -0.032600417733192444, -0.01862197183072567, -0.016264304518699646, 0.12733790278434753, 0.024725573137402534, 0.0036681455094367266, -0.007527776528149843, 0.07448788732290268, 0.0374593660235405, 0.0012887875782325864, -0.058690328150987625, -0.010232510045170784, -0.1169019415974617, 0.04014016315340996, 0.06634975224733353, -0.056105270981788635, 0.006725930608808994, 0.108285091817379, 0.05749354138970375, 0.0081022335216403, -0.12762513756752014, -0.046602800488471985, -0.061466868966817856, -0.007444001268595457, -0.04502304270863533, 0.07238154113292694, -0.042557667940855026, -0.08008883893489838, 0.030565883964300156], 'score': 3.780266761779785}, page_content='The complexity of the human brain has made it difficult to study many brain disorders in model organisms, highlighting the need for an in vitro model of human brain development. Here we have developed a human pluripotent stem cell-derived three-dimensional organoid culture system, termed cerebral organoids, that develop various discrete, although interdependent, brain regions. These include a cerebral cortex containing progenitor populations that organize and produce mature cortical neuron subtypes. Furthermore, cerebral organoids are shown to recapitulate features of human cortical development, namely characteristic progenitor zone organization with abundant outer radial glial stem cells. Finally, we use RNA interference and patient-specific induced pluripotent stem cells to model microcephaly, a disorder that has been difficult to recapitulate in mice. We demonstrate premature neuronal differentiation in patient organoids, a defect that could help to explain the disease phenotype. Together, these data show that three-dimensional organoids can recapitulate development and disease even in this most complex human tissue.'),\n", - " Document(metadata={'_id': '10906636', 'title': 'The carboxyl terminus of human cytomegalovirus-encoded 7 transmembrane receptor US28 camouflages agonism by mediating constitutive endocytosis.', 'embedding': [-0.031789202243089676, 0.04996145889163017, 0.0008426404092460871, 0.10550684481859207, -0.11373579502105713, 0.0509410984814167, 0.07332579046487808, -0.058974117040634155, 0.03852420300245285, -0.08126084506511688, 0.05481066182255745, -0.0001735410769470036, 0.027699220925569534, 0.04616536945104599, 0.05564335361123085, -0.12000546604394913, -0.053439170122146606, 0.023229630663990974, -0.02718491293489933, 0.08326909691095352, 0.0722481906414032, 0.05123498663306236, -0.03338111191987991, 0.10511499643325806, -0.08390586078166962, -0.009686155244708061, 0.014204729348421097, 0.016482383012771606, -0.055447425693273544, 0.027821676805615425, 0.04626333341002464, -0.05236157029867172, 0.0005981139838695526, -0.09595539420843124, -0.13264277577400208, 0.07131753861904144, 0.03583020344376564, 0.03431176766753197, 0.0005747710820287466, 0.05392898619174957, 0.0661744475364685, -0.043275441974401474, 0.020180512219667435, -0.0013913899892941117, -0.08160372078418732, -0.05152887850999832, -0.15008030831813812, 0.01611502096056938, 0.03443422168493271, 0.03073609434068203, 0.028923766687512398, -0.01082498300820589, 0.03734863921999931, 0.084346704185009, -0.12098510563373566, -0.008296296000480652, 0.039871204644441605, 0.044671423733234406, -0.02551952935755253, -0.04449998587369919, 0.028825802728533745, -0.07856684178113937, -0.025299111381173134, -0.06029662489891052, -0.04915326088666916, -0.06073746085166931, -0.10119644552469254, -0.015208856202661991, 0.0386221669614315, -0.015429274179041386, 0.0014679239830002189, -0.045822497457265854, -0.05314527824521065, 0.04606740549206734, 0.034483205527067184, -0.0457245334982872, 0.02877682074904442, 0.035609785467386246, -0.059268005192279816, -0.08488550037145615, 0.0208785030990839, -0.0004622659762389958, 0.042001914232969284, -0.029927894473075867, 0.028972748667001724, -0.001702118432149291, 0.0653417557477951, -0.0745503380894661, -0.022543884813785553, 0.07082771509885788, -0.02461336739361286, 0.09972698986530304, -0.13264277577400208, 0.09193888306617737, -0.048100151121616364, 0.042981550097465515, -0.052753422409296036, -0.0849834606051445, 0.050353314727544785, 0.017633456736803055, -0.056427061557769775, -0.024735821411013603, -0.007488096132874489, -0.0031746344175189734, -0.009086128324270248, 0.04307951405644417, -0.0920858308672905, 0.045234713703393936, 0.0620109885931015, -0.03771600499749184, 0.3113284707069397, -0.019641710445284843, -0.0595129169523716, 0.10344961285591125, -0.01634768396615982, -0.08993063122034073, -0.10766205191612244, 0.04817362502217293, 0.013127128593623638, 0.02618078514933586, -0.03609960526227951, 0.06294164061546326, 0.04533267766237259, 0.020474402233958244, -0.04378975182771683, 0.032352495938539505, 0.08738357573747635, -0.0004974716575816274, -0.08243641257286072, -0.04498980566859245, 0.126960888504982, -0.0563780777156353, -0.0668112114071846, 0.0171191468834877, -0.07440339028835297, 0.008804482407867908, 0.021637720987200737, -0.06588055193424225, -0.08468957245349884, 0.0628436803817749, -0.011265819892287254, 0.029682984575629234, -0.013714910484850407, 0.0008931529591791332, -0.09091026335954666, -0.014951701276004314, -0.12206270545721054, 0.18740445375442505, 0.04621434956789017, 0.049643076956272125, 0.0793505534529686, 0.03134836629033089, 0.1208871379494667, -0.04246724024415016, -0.020180512219667435, -0.06191302463412285, -0.006563564296811819, 0.0340423658490181, -0.05059822276234627, 0.04942265897989273, 0.04690009728074074, 0.050353314727544785, -0.050206370651721954, 0.044402021914720535, 0.028384966775774956, -0.009918819181621075, -0.05525149777531624, -0.014376165345311165, -0.15634998679161072, -0.042418260127305984, -0.008694273419678211, -0.06568462401628494, -0.1380307823419571, -0.05187175050377846, -0.10589870065450668, 0.07352171838283539, 0.015943583101034164, -0.008994287811219692, -0.028409458696842194, 0.033772967755794525, 0.02288675680756569, 0.05907208099961281, 0.07190531492233276, -0.028703348711133003, 0.05099007859826088, -0.021429548040032387, -0.052165642380714417, 0.09620030224323273, -0.06700713187456131, 0.021454038098454475, -0.022372448816895485, -0.04244275018572807, 0.14625972509384155, 0.043422386050224304, -0.03147082030773163, 0.005388000514358282, 0.04065491259098053, 0.017804892733693123, 0.00404100026935339, -0.12020139396190643, -0.054026950150728226, 0.054712697863578796, -0.022972475737333298, -0.10638852417469025, -0.09815957397222519, 0.018221238628029823, -0.01942129246890545, 0.047928713262081146, -0.01388634741306305, -0.0417570061981678, 0.06989706307649612, 0.023388821631669998, 0.028384966775774956, 0.06783982366323471, -0.009061637334525585, -0.035879187285900116, -0.07572589814662933, 0.007910564541816711, -0.0021659149788320065, 0.013690419495105743, 0.047659315168857574, 0.048638951033353806, 0.0388425849378109, 0.017302829772233963, -0.09629826247692108, 0.012894464656710625, -0.07807702571153641, -0.11540117859840393, -0.084346704185009, 0.0014663933543488383, 0.027723712846636772, 0.04376525804400444, 0.015980320051312447, -0.09512270241975784, -0.046973567456007004, 0.044842857867479324, -0.003067486686632037, -0.00983310118317604, 0.07322783023118973, -0.04165904223918915, -0.04219784215092659, 0.022347956895828247, 0.04577351361513138, 0.1474352926015854, -0.046826623380184174, 0.006716632749885321, -0.032376985996961594, -0.0657825917005539, -0.06044356897473335, 0.002020500134676695, 0.03472811356186867, -0.01691097393631935, -0.014437392354011536, -0.0075187101028859615, -0.05270444229245186, 0.06676222383975983], 'score': 3.7103075981140137}, page_content='US28 is one of four 7 transmembrane (7TM) chemokine receptors encoded by human cytomegalovirus and has been shown to both signal and endocytose in a ligand-independent, constitutively active manner. Here we show that the constitutive activity and constitutive endocytosis properties of US28 are separable entities in this viral chemokine receptor. We generated chimeric and mutant US28 proteins that were altered in either their constitutive endocytic (US28 Delta 300, US28 Delta 317, US28-NK1-ctail, and US28-ORF74-ctail) or signaling properties (US28R129A). By using this series of mutants, we show that the cytoplasmic tail domain of US28 per se regulates receptor endocytosis, independent of the signaling ability of the core domain of US28. The constitutive endocytic property of the US28 c-tail was transposable to other 7TM receptors, the herpes virus 8-encoded ORF74 and the tachykinin NK1 receptor (ORF74-US28-ctail and NK1-US28-ctail). Deletion of the US28 C terminus resulted in reduced constitutive endocytosis and consequently enhanced signaling capacity of all receptors tested as assessed by inositol phosphate turnover, NF-kappa B, and cAMP-responsive element-binding protein transcription assays. We further show that the constitutive endocytic property of US28 affects the action of its chemokine ligand fractalkine/CX3CL1 and show that in the absence of the US28 C terminus, fractalkine/CX3CL1 acts as an agonist on US28. This demonstrates for the first time that the endocytic properties of a 7TM receptor can camouflage the agonist properties of a ligand.'),\n", - " Document(metadata={'_id': '13231899', 'title': 'In situ regulation of DC subsets and T cells mediates tumor regression in mice.', 'embedding': [0.07147765904664993, 0.059025105088949203, 0.09424092620611191, 0.1306023895740509, -0.033123794943094254, 0.049835119396448135, 0.099271759390831, 0.07611000537872314, -0.05334674194455147, 0.07929786294698715, 0.006786641664803028, 0.033049076795578, -0.025851501151919365, 0.016860757023096085, 0.03235173597931862, -0.04368355870246887, 0.11536046117544174, 0.02443191036581993, 0.06749284267425537, 0.08652034401893616, 0.05439275503158569, 0.05018379166722298, 0.003947459626942873, -0.04418165981769562, -0.04639821499586105, -0.031106479465961456, -0.007583605125546455, 0.05718212574720383, 0.06749284267425537, 0.05025850608944893, 0.055289339274168015, -0.053645603358745575, -0.0743168443441391, -0.024506626650691032, -0.11575894057750702, 0.03671012818813324, 0.03090723790228367, 0.023734567686915398, 0.008112838491797447, 0.011605780571699142, 0.01672377996146679, -0.023099487647414207, -0.08074235916137695, 0.12691642343997955, -0.058477193117141724, -0.0939420685172081, -0.05553838983178139, -0.10639461874961853, 0.022302523255348206, -0.02353532612323761, 0.043185457587242126, 0.03705880045890808, -0.044480521231889725, 0.14086328446865082, -0.13149896264076233, 0.12054072320461273, 0.001376007217913866, 0.031006859615445137, 0.007932276464998722, -0.006936072371900082, 0.003583222394809127, -0.034941866993904114, 0.06774189323186874, -0.044928815215826035, -0.06644682586193085, -0.03877725079655647, -0.09075421094894409, -0.10450182855129242, 0.03641126677393913, -0.07267310470342636, 0.0033186054788529873, -0.039026305079460144, -0.00028660331736318767, 0.016512086614966393, 0.04612426087260246, 0.02388399839401245, 0.03778104856610298, 0.014519677497446537, -0.01290084607899189, -0.06779170036315918, 0.06515175849199295, 0.01854185201227665, 0.06679549813270569, -0.06271106004714966, -0.0575806088745594, -0.022402144968509674, 0.02209082990884781, 0.00845528393983841, -0.15341545641422272, -0.01754564791917801, 0.044281281530857086, 0.06943544000387192, -0.057829659432172775, 0.0937926322221756, -0.03561430424451828, -0.019774654880166054, -0.008498867973685265, -0.10041739046573639, 0.024830391630530357, 0.045103151351213455, 0.08059293031692505, -0.053745221346616745, 0.008218685165047646, -0.07526323199272156, 0.05030831694602966, -0.043185457587242126, -0.051105279475450516, 0.04089418798685074, 0.04981021583080292, 0.03541506454348564, 0.27873796224594116, 0.05160338431596756, 0.01148748118430376, 0.03359698876738548, -0.07456589490175247, -0.08507584780454636, -0.11546007543802261, 0.008785276673734188, 0.020471997559070587, 0.0412677638232708, -0.00971299223601818, 0.03845348581671715, 0.0015931485686451197, -0.029512552544474602, 0.020322568714618683, -0.04717027395963669, 0.09503789246082306, -0.04186548665165901, -0.11416501551866531, -0.03424452245235443, 0.09319490939378738, -0.045202769339084625, 0.07421722263097763, -0.035564493387937546, -0.12083958089351654, -0.08532489836215973, 0.03937497362494469, -0.0012374725192785263, -0.00782020390033722, 0.01790677197277546, 0.03887687250971794, -0.010472597554326057, 0.0038135945796966553, -0.006030149292200804, -0.08871199190616608, -0.13558340072631836, 0.04844043403863907, 0.017944129183888435, 0.030683092772960663, 0.05235053598880768, -0.00859226193279028, 0.11426463723182678, 0.15660332143306732, 0.09663181751966476, -0.02125651016831398, -0.07351987808942795, 0.02018558979034424, 0.12920770049095154, -0.0047973464243113995, -0.08213704824447632, -0.08313325047492981, 0.04505334049463272, -0.07491456717252731, -0.02724618837237358, 0.06271106004714966, 0.0012631559511646628, -0.004349054303020239, 0.09244775772094727, -0.11057867854833603, -0.05324712023139, -0.05289844796061516, -0.1077893078327179, -0.09857441484928131, 0.027096757665276527, -0.08378078043460846, -0.023385895416140556, 0.06878791004419327, 0.09100326150655746, -0.034842245280742645, 0.0015853657387197018, 0.0014732928248122334, 0.06440460681915283, 0.022738363593816757, 0.05058227479457855, -0.03952440619468689, 0.04652274027466774, 0.014009122736752033, 0.042836785316467285, -0.0730217769742012, 0.016935473307967186, 0.03725804015994072, -0.04734461009502411, 0.03790557384490967, -0.00612976960837841, 0.020048610866069794, -0.005566291511058807, 0.06071865186095238, 0.0008919141837395728, 0.05768023058772087, -0.08114083856344223, 0.0769069716334343, -0.00020721828332170844, -0.1525188833475113, 0.0041840579360723495, -0.04203982278704643, -0.005510255228728056, -0.05499047785997391, 0.10499993711709976, -0.016424918547272682, -0.019139574840664864, 0.03842858225107193, 0.017408670857548714, -0.005027718376368284, -0.013286874629557133, 0.0066185323521494865, -0.02926350198686123, -0.10888513177633286, 0.010933342389762402, 0.04385789483785629, 0.05708250775933266, 0.08472717553377151, -0.02552773617208004, 0.016462275758385658, -0.0041840579360723495, -0.0058153425343334675, -0.019139574840664864, 0.0379553847014904, -0.059025105088949203, -0.027022041380405426, -0.0029870562721043825, -0.04071985185146332, -0.01570267044007778, 0.022514216601848602, -0.09593447297811508, -0.074466273188591, -0.035215821117162704, 0.03407018631696701, 0.024481721222400665, 0.11625704169273376, -0.06619777530431747, 0.017744889482855797, -0.013324232771992683, 0.043733369559049606, 0.0688377171754837, -0.0799453929066658, 0.06629739701747894, -0.005077528767287731, -0.13100086152553558, -0.11057867854833603, 0.015403809025883675, -0.023933809250593185, 0.018043750897049904, 0.04669707641005516, -0.054641805589199066, -0.041915297508239746, 0.04480428993701935], 'score': 3.52976655960083}, page_content='Vaccines are largely ineffective for patients with established cancer, as advanced disease requires potent and sustained activation of CD8(+) cytotoxic T lymphocytes (CTLs) to kill tumor cells and clear the disease. Recent studies have found that subsets of dendritic cells (DCs) specialize in antigen cross-presentation and in the production of cytokines, which regulate both CTLs and T regulatory (Treg) cells that shut down effector T cell responses. Here, we addressed the hypothesis that coordinated regulation of a DC network, and plasmacytoid DCs (pDCs) and CD8(+) DCs in particular, could enhance host immunity in mice. We used functionalized biomaterials incorporating various combinations of an inflammatory cytokine, immune danger signal, and tumor lysates to control the activation and localization of host DC populations in situ. The numbers of pDCs and CD8(+) DCs, and the endogenous production of interleukin-12, all correlated strongly with the magnitude of protective antitumor immunity and the generation of potent CD8(+) CTLs. Vaccination by this method maintained local and systemic CTL responses for extended periods while inhibiting FoxP3 Treg activity during antigen clearance, resulting in complete regression of distant and established melanoma tumors. The efficacy of this vaccine as a monotherapy against large invasive tumors may be a result of the local activity of pDCs and CD8(+) DCs induced by persistent danger and antigen signaling at the vaccine site. These results indicate that a critical pattern of DC subsets correlates with the evolution of therapeutic antitumor responses and provide a template for future vaccine design.'),\n", - " Document(metadata={'_id': '3770726', 'title': 'Microfluidic platform to evaluate migration of cells from patients with DYT1 dystonia.', 'embedding': [0.01717449352145195, 0.04425951838493347, 0.012141804210841656, 0.09679657965898514, -0.04856721684336662, 0.00971344392746687, -0.0068627591244876385, 0.005148828960955143, 0.023087024688720703, -0.038065437227487564, 0.05084776505827904, -0.026592310518026352, -0.009945721365511417, -0.03395482152700424, -0.018159916624426842, 0.03952949121594429, 0.045836191624403, -0.12117872387170792, 0.0071196723729372025, 0.10451102256774902, 0.11543512344360352, 0.013056838884949684, -0.014168958179652691, -0.05087592080235481, 0.05107300356030464, -0.040486760437488556, 0.06638927757740021, -0.04527309164404869, 0.011121189221739769, -0.06520676612854004, 0.025142334401607513, -0.05346617102622986, 0.01766720600426197, -0.06678344309329987, -0.05290307477116585, 0.06988048553466797, 0.09882372617721558, 0.12714757025241852, -0.06959893554449081, 0.04501969739794731, 0.050059426575899124, -0.045610953122377396, 0.00763701880350709, 0.10445471107959747, -0.03271600231528282, -0.038938239216804504, -0.030688850209116936, -0.030801469460129738, 0.060476742684841156, 0.05239628627896309, -0.023255955427885056, 0.022904017940163612, -0.05757678672671318, 0.018779324367642403, -0.06261651962995529, 0.031308259814977646, 0.009762714616954327, 0.020384153351187706, 0.0074962442740798, 0.0071407887153327465, 0.02335449680685997, -0.059913646429777145, 0.1428017020225525, -0.06137770041823387, 0.010684788227081299, 0.00864355731755495, -0.13998620212078094, 0.01542888954281807, 0.009600823745131493, 0.036319833248853683, 0.013774788938462734, -0.06323592364788055, 0.07427264750003815, -0.10670710355043411, 0.0034595343749970198, -0.030829625204205513, 0.03840329498052597, 0.055662255734205246, -0.008460549637675285, 0.09048987925052643, 0.040064435452222824, -0.10192076861858368, -0.0802977979183197, 0.011100072413682938, -0.02066570334136486, -0.00722877262160182, 0.005071402993053198, -0.11076141148805618, -0.08756176382303238, 0.012817522510886192, -0.03814990073442459, 0.014626475051045418, -0.05901268869638443, 0.1317649781703949, 0.05219919979572296, -0.011114150285720825, 0.017962832003831863, -0.07663766294717789, 0.0027890957426279783, -0.0314771868288517, 0.0634048581123352, 0.04913031682372093, -0.018385155126452446, 0.021749667823314667, 0.11380214244127274, -0.041500333696603775, -0.12478255480527878, -0.00424435269087553, 0.020933175459504128, 0.08035410940647125, 0.1545141339302063, -0.020158914849162102, -0.028267528861761093, 0.09538882970809937, 0.06931738555431366, -0.048933230340480804, -0.03851591423153877, -0.0691484585404396, -0.0069437045603990555, 0.04462553188204765, -0.07810171693563461, 0.076975516974926, 0.04797596484422684, -0.009882372803986073, 0.08677342534065247, -0.09172869473695755, -0.006341893225908279, 0.006764216814190149, -0.20327843725681305, -0.09364322572946548, 0.0516924113035202, -0.012479662895202637, 0.009537475183606148, -0.059237927198410034, -0.10186445713043213, -0.0012669708812609315, 0.016020143404603004, 0.13390474021434784, -0.03640429675579071, 0.08300066739320755, -0.023396728560328484, -0.039247941225767136, 0.10817115753889084, 0.047807034105062485, -0.03857222571969032, 0.0009871814399957657, 0.010325812734663486, 0.13615714013576508, 0.07404740899801254, 0.1146467849612236, 0.01304979994893074, 0.0031111175194382668, 0.01592160016298294, 0.006711426191031933, 0.03260338306427002, -0.003283566329628229, 0.08823748677968979, 0.1264718472957611, -0.019469119608402252, -0.12512041628360748, -0.08142399787902832, -0.019131259992718697, -0.0855909213423729, -0.03280046954751015, -0.0315898060798645, 0.09268596023321152, -0.08209971338510513, -0.03035099245607853, -0.10693234205245972, -0.04676530510187149, -0.045864347368478775, -0.02835199236869812, -0.126359224319458, 0.009403739124536514, -0.06013888493180275, -0.08722390979528427, 0.0009739839006215334, -0.0033662712667137384, -0.014823559671640396, 0.03372957929968834, -0.027366571128368378, 0.09696550667285919, 0.058731138706207275, -0.02241130731999874, -0.02372051030397415, -0.007313237525522709, -0.0031498305033892393, 0.12455731630325317, -0.00918553862720728, 0.0010672470089048147, -0.009157383814454079, 0.04558279737830162, 0.05695737898349762, -0.008573169820010662, -0.0031551094725728035, -0.038684844970703125, 0.15237437188625336, 0.04003627970814705, 0.031139329075813293, -0.06706499308347702, 0.02947818860411644, -0.04769441485404968, -0.07956577092409134, -0.08423949033021927, -0.04045860469341278, 0.06948631256818771, -0.0025568176060914993, 0.03646060824394226, -0.0014930899487808347, 0.0032342951744794846, 0.035306256264448166, 0.08812486380338669, -0.06278544664382935, 0.06503783911466599, 0.03035099245607853, 0.003980400040745735, -0.04403427615761757, 0.0970781221985817, 0.10805854201316833, -0.05470498651266098, -0.03941687196493149, 0.06486891210079193, 0.08480258285999298, 0.17489829659461975, -0.08705497533082962, -0.017695359885692596, 0.05737970396876335, -0.03691108524799347, -0.05507100000977516, -0.05326908826828003, 0.040374137461185455, 0.07534253597259521, 0.017582740634679794, -0.06926107406616211, 0.007545515429228544, 0.030998554080724716, -0.01624538190662861, -0.05312831327319145, 0.11577298492193222, -0.08097352087497711, 0.022256454452872276, 0.0473284013569355, -0.059237927198410034, -0.10873425751924515, -0.00714782765135169, -0.04772257059812546, -0.0747794359922409, -0.05794280394911766, 0.03615090250968933, -0.045864347368478775, -0.08063565939664841, 0.08159292489290237, 0.04014889895915985, -0.047609951347112656, -0.011142305098474026, -0.004437917377799749], 'score': 3.4964065551757812}, page_content=\"BACKGROUND Microfluidic platforms for quantitative evaluation of cell biologic processes allow low cost and time efficient research studies of biological and pathological events, such as monitoring cell migration by real-time imaging. In healthy and disease states, cell migration is crucial in development and wound healing, as well as to maintain the body's homeostasis. NEW METHOD The microfluidic chambers allow precise measurements to investigate whether fibroblasts carrying a mutation in the TOR1A gene, underlying the hereditary neurologic disease--DYT1 dystonia, have decreased migration properties when compared to control cells. RESULTS We observed that fibroblasts from DYT1 patients showed abnormalities in basic features of cell migration, such as reduced velocity and persistence of movement. COMPARISON WITH EXISTING METHOD The microfluidic method enabled us to demonstrate reduced polarization of the nucleus and abnormal orientation of nuclei and Golgi inside the moving DYT1 patient cells compared to control cells, as well as vectorial movement of single cells. CONCLUSION We report here different assays useful in determining various parameters of cell migration in DYT1 patient cells as a consequence of the TOR1A gene mutation, including a microfluidic platform, which provides a means to evaluate real-time vectorial movement with single cell resolution in a three-dimensional environment.\")]" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "full_text_search(db[CORPUS_COLLECTION_NAME], \"0-dimensional biomaterials show inductive properties\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "QFdAtnF0RQ_H" - }, - "source": [ - "### Vector Search LangChain<>MongoDB Integration" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "DrtO8trFRejZ" - }, - "outputs": [], - "source": [ - "from langchain_openai import OpenAIEmbeddings\n", - "from langchain_mongodb import MongoDBAtlasVectorSearch\n", - "\n", - "# Initialize embeddings model\n", - "embedding_model = OpenAIEmbeddings(model=EMBEDDING_MODEL, dimensions=EMBEDDING_DIMENSION_SIZE)\n", - "\n", - "# Initialize vector store\n", - "vector_store = MongoDBAtlasVectorSearch.from_connection_string(\n", - " connection_string=MONGO_URI,\n", - " namespace=f\"{DB_NAME}.{CORPUS_COLLECTION_NAME}\",\n", - " embedding=embedding_model,\n", - " index_name=ATLAS_VECTOR_SEARCH_INDEX,\n", - " text_key=\"text\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "xQrTmWl4RuQP" - }, - "outputs": [], - "source": [ - "# Search functions\n", - "def vector_search(query: str, top_k: int = 10) -> List[Tuple[Any, float]]:\n", - " return vector_store.similarity_search_with_score(query=query, k=top_k)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "9YJxAyprRvf8", - "outputId": "67014648-28d1-46d8-85c7-61d1f13b946a" - }, - "outputs": [ - { - "data": { - "text/plain": [ - "[(Document(metadata={'_id': '4346436', 'title': 'Nonlinear Elasticity in Biological Gels'}, page_content='Unlike most synthetic materials, biological materials often stiffen as they are deformed. This nonlinear elastic response, critical for the physiological function of some tissues, has been documented since at least the 19th century, but the molecular structure and the design principles responsible for it are unknown. Current models for this response require geometrically complex ordered structures unique to each material. In this Article we show that a much simpler molecular theory accounts for strain stiffening in a wide range of molecularly distinct biopolymer gels formed from purified cytoskeletal and extracellular proteins. This theory shows that systems of semi-flexible chains such as filamentous proteins arranged in an open crosslinked meshwork invariably stiffen at low strains without the need for a specific architecture or multiple elements with different intrinsic stiffnesses.'),\n", - " 0.7601195573806763),\n", - " (Document(metadata={'_id': '927561', 'title': 'Emergent structures and dynamics of cell colonies by contact inhibition of locomotion'}, page_content='Cells in tissues can organize into a broad spectrum of structures according to their function. Drastic changes of organization, such as epithelial-mesenchymal transitions or the formation of spheroidal aggregates, are often associated either to tissue morphogenesis or to cancer progression. Here, we study the organization of cell colonies by means of simulations of self-propelled particles with generic cell-like interactions. The interplay between cell softness, cell-cell adhesion, and contact inhibition of locomotion (CIL) yields structures and collective dynamics observed in several existing tissue phenotypes. These include regular distributions of cells, dynamic cell clusters, gel-like networks, collectively migrating monolayers, and 3D aggregates. We give analytical predictions for transitions between noncohesive, cohesive, and 3D cell arrangements. We explicitly show how CIL yields an effective repulsion that promotes cell dispersal, thereby hindering the formation of cohesive tissues. Yet, in continuous monolayers, CIL leads to collective cell motion, ensures tensile intercellular stresses, and opposes cell extrusion. Thus, our work highlights the prominent role of CIL in determining the emergent structures and dynamics of cell colonies.'),\n", - " 0.7536574006080627),\n", - " (Document(metadata={'_id': '19685306', 'title': 'Orientationally invariant indices of axon diameter and density from diffusion MRI.'}, page_content='This paper proposes and tests a technique for imaging orientationally invariant indices of axon diameter and density in white matter using diffusion magnetic resonance imaging. Such indices potentially provide more specific markers of white matter microstructure than standard indices from diffusion tensor imaging. Orientational invariance allows for combination with tractography and presents new opportunities for mapping brain connectivity and quantifying disease processes. The technique uses a four-compartment tissue model combined with an optimized multishell high-angular-resolution pulsed-gradient-spin-echo acquisition. We test the method in simulation, on fixed monkey brains using a preclinical scanner and on live human brains using a clinical 3T scanner. The human data take about one hour to acquire. The simulation experiments show that both monkey and human protocols distinguish distributions of axon diameters that occur naturally in white matter. We compare the axon diameter index with the mean axon diameter weighted by axon volume. The index differs from this mean and is protocol dependent, but correlation is good for the monkey protocol and weaker, but discernible, for the human protocol where greater diffusivity and lower gradient strength limit sensitivity to only the largest axons. Maps of axon diameter and density indices from the monkey and human data in the corpus callosum and corticospinal tract reflect known trends from histology. The results show orientationally invariant sensitivity to natural axon diameter distributions for the first time with both specialist and clinical hardware. This demonstration motivates further refinement, validation, and evaluation of the precise nature of the indices and the influence of potential confounds.'),\n", - " 0.742658793926239),\n", - " (Document(metadata={'_id': '17388232', 'title': 'Mechanical regulation of cell function with geometrically modulated elastomeric substrates'}, page_content='We report the establishment of a library of micromolded elastomeric micropost arrays to modulate substrate rigidity independently of effects on adhesive and other material surface properties. We demonstrated that micropost rigidity impacts cell morphology, focal adhesions, cytoskeletal contractility and stem cell differentiation. Furthermore, early changes in cytoskeletal contractility predicted later stem cell fate decisions in single cells.'),\n", - " 0.7384290099143982),\n", - " (Document(metadata={'_id': '14082855', 'title': 'Inflammatory Reaction as Determinant of Foreign Body Reaction Is an Early and Susceptible Event after Mesh Implantation'}, page_content='PURPOSE To investigate and relate the ultrashort-term and long-term courses of determinants for foreign body reaction as biocompatibility predictors for meshes in an animal model. MATERIALS AND METHODS Three different meshes (TVT, UltraPro, and PVDF) were implanted in sheep. Native and plasma coated meshes were placed bilaterally: (a) interaperitoneally, (b) as fascia onlay, and (c) as muscle onlay (fascia sublay). At 5 min, 20 min, 60 min, and 120 min meshes were explanted and histochemically investigated for inflammatory infiltrate, macrophage infiltration, vessel formation, myofibroblast invasion, and connective tissue accumulation. The results were related to long-term values over 24 months. RESULTS Macrophage invasion reached highest extents with up to 60% in short-term and decreased within 24 months to about 30%. Inflammatory infiltrate increased within the first 2 hours, the reached levels and the different extents and ranking among the investigated meshes remained stable during long-term follow up. For myofibroblasts, connective tissue, and CD31+ cells, no activity was detected during the first 120 min. CONCLUSION The local inflammatory reaction is an early and susceptible event after mesh implantation. It cannot be influenced by prior plasma coating and does not depend on the localisation of implantation.'),\n", - " 0.7378800511360168),\n", - " (Document(metadata={'_id': '28071965', 'title': 'A Balance between Secreted Inhibitors and Edge Sensing Controls Gastruloid Self-Organization.'}, page_content='The earliest aspects of human embryogenesis remain mysterious. To model patterning events in the human embryo, we used colonies of human embryonic stem cells (hESCs) grown on micropatterned substrate and differentiated with BMP4. These gastruloids recapitulate the embryonic arrangement of the mammalian germ layers and provide an assay to assess the structural and signaling mechanisms patterning the human gastrula. Structurally, high-density hESCs localize their receptors to transforming growth factor β at their lateral side in the center of the colony while maintaining apical localization of receptors at the edge. This relocalization insulates cells at the center from apically applied ligands while maintaining response to basally presented ones. In addition, BMP4 directly induces the expression of its own inhibitor, NOGGIN, generating a reaction-diffusion mechanism that underlies patterning. We develop a quantitative model that integrates edge sensing and inhibitors to predict human fate positioning in gastruloids and, potentially, the human embryo.'),\n", - " 0.7353475689888),\n", - " (Document(metadata={'_id': '39291138', 'title': 'Integration of Smad and MAPK pathways: a link and a linker revisited.'}, page_content='Cells develop by reading mixed signals. Nowhere is this clearer than in the highly dynamic processes that propel embryogenesis, when critical cell-fate decisions are made swiftly in response to well-orchestrated growthfactor combinations. Learning how diverse signaling pathways are integrated is therefore essential for understanding physiology. This requires the identification, in tangible molecular terms, of key nodes for pathway integration that operate in vivo. A report in this issue, on the integration of Smad and Ras/MAPK pathways during neural induction (Pera et al. 2003), provides timely insights into the relevance of one such node. Pera et al. (2003) report that FGF8 and IGF2—two growth factors that activate the Ras/MAPK pathway— favor neural differentiation and mesoderm dorsalization in Xenopus by inhibiting BMP (Bone Morphogenetic Protein) signaling. Mesoderm is formed from ectoderm in response to Nodal-related signals from the endoderm at the blastula stage and beyond (Fig. 1; for review, see De Robertis et al. 2000). BMP induces differentiation of ectoderm into epidermal cell fates at the expense of neural fates, and it ventralizes the mesoderm at the expense of dorsal fates (for review, see Weinstein and HemmatiBrivanlou 1999; De Robertis et al. 2000). Accordingly, neural differentiation and dorsal mesoderm formation are favored when BMP signaling is attenuated. Noggin, Chordin, Cerberus, and Follistatin, secreted by the Spemann organizer on the dorsal side at the gastrula stage, facilitate the formation of neural tissue by sequestering BMP (Weinstein and Hemmati-Brivanlou 1999; De Robertis et al. 2000). Experimentally blocking BMP signaling with a dominant-negative BMP receptor has a similar effect of promoting ectoderm neuralization (Weinstein and Hemmati-Brivanlou 1999). As it turns out, neural induction can also be achieved with FGF (fibroblast growth factor; Kengaku and Okamoto 1993; Lamb and Harland 1995; Hongo et al. 1999; Hardcastle et al. 2000; Streit et al. 2000; Wilson et al. 2000) and IGF (insulin-like growth factor; Pera et al. 2001; Richard-Parpaillon et al. 2002). Injection of transcripts encoding FGF8 or IFG2 into one animal-pole blastomere of a fourto eight-cell embryo results in an expanded neural plate at the injected side (Pera et al. 2003). Surprisingly, expression of a dominant-negative FGF receptor prevents neuralization of ectoderm explants by the BMP blocker Noggin (Launay et al. 1996). Likewise, the potent neuralizing effect of Chordin can be blocked by a dominant-negative FGF receptor or a morpholino oligonucleotide targeting the IGF receptor (Pera et al. 2003). Thus, the neuralizing effect of BMP inhibitors is somehow tied to FGF and IFG signaling. The question is, how? Because FGF8 and IFG2 activate MAPK, Pera et al. (2003) took heed from previous work showing that MAPK inhibits the BMP signal-transduction factor Smad1 (Kretzschmar et al. 1997a). Smad1 is directly phosphorylated by the BMP receptor, resulting in Smad1 activation (Kretzschmar et al. 1997b), and by MAPK in response to EGF, resulting in Smad1 inhibition (Kretzschmar et al. 1997a; Fig. 2). Smad transcription factors mediate gene responses to the entire TGF (Transforming Growth Factor) family, to which the BMPs belong (for review, see Massague 2000; Derynck and Zhang 2003). Smads 1, 5, and 8 act primarily downstream of BMP receptors and Smads 2 and 3 downstream of TGF , Activin and Nodal receptors. Smad proteins have two conserved globular domains—the MH1 and MH2 domains (Fig. 2). The MH1 domain is involved in DNA binding and the MH2 domain in binding to cytoplasmic retention factors, activated receptors, nucleoporins in the nuclear pore, and DNA-binding cofactors, coactivators, and corepressors in the nucleus (for review, see Shi and Massague 2003). Receptor-mediated phosphorylation occurs at the carboxy-terminal sequence SXS. This enables the nuclear accumulation of Smads and their association with the shared partner Smad4 to form transcriptional complexes that are interpreted by the cell as a function of the context (Massague 2000). Between the MH1 and MH2 domains lies a linker region of variable sequence and length. Attention was drawn to this region when it was found that EGF (epidermal growth factor), a classical activator of the Ras/ MAPK pathway, causes phosphorylation of the Smad1 linker at four MAPK sites (PXSP sequences; Kretzschmar et al. 1997a). This prevents the nuclear localization of Smad1 and inhibits BMP signaling. Mutation of these E-MAIL j-massague@ski.mskcc.org; FAX (212) 717-3298. Article and publication are at http://www.genesdev.org/cgi/doi/10.1101/ gad.1167003.'),\n", - " 0.7275398969650269),\n", - " (Document(metadata={'_id': '43990286', 'title': 'Cell and biomolecule delivery for tissue repair and regeneration in the central nervous system.'}, page_content='Tissue engineering frequently involves cells and scaffolds to replace damaged or diseased tissue. It originated, in part, as a means of effecting the delivery of biomolecules such as insulin or neurotrophic factors, given that cells are constitutive producers of such therapeutic agents. Thus cell delivery is intrinsic to tissue engineering. Controlled release of biomolecules is also an important tool for enabling cell delivery since the biomolecules can enable cell engraftment, modulate inflammatory response or otherwise benefit the behavior of the delivered cells. We describe advances in cell and biomolecule delivery for tissue regeneration, with emphasis on the central nervous system (CNS). In the first section, the focus is on encapsulated cell therapy. In the second section, the focus is on biomolecule delivery in polymeric nano/microspheres and hydrogels for the nerve regeneration and endogenous cell stimulation. In the third section, the focus is on combination strategies of neural stem/progenitor cell or mesenchymal stem cell and biomolecule delivery for tissue regeneration and repair. In each section, the challenges and potential solutions associated with delivery to the CNS are highlighted.'),\n", - " 0.7260926961898804),\n", - " (Document(metadata={'_id': '7583104', 'title': 'IDEAL in meshes for prolapse, urinary incontinence, and hernia repair.'}, page_content='PURPOSE Mesh surgeries are counted among the most frequently applied surgical procedures. Despite global spread of mesh applying surgeries, there is no current systematic analysis of incidence and possible prevention of adverse events after mesh implantation. MATERIALS AND METHODS Based on the recommendations of IDEAL an in vitro test system for biocompatibility of surgical meshes has been generated (Innovation). Coating strategies for biocompatibility optimization have been developed (Development). The native and modified alloplastic materials have been tested in an animal model over 2 years (Exploration and Assessment and Long-term study). RESULTS In 3 meshes, implanted in sheep and explanted at 4 different time points (a, 3 months; b, 6 months; c, 12 months; and d, 24 months) over 24 months, thickness of inflammatory tissue (TVT a, 35 µm; b, 32 µm; c, 33 µm; d, 28 µm; UltraPro, a, 25 µm; b, 24 µm; c, 21 µm; d, 22 µm; PVDF a, 20 µm; b, 21 µm; c, 14 µm; d, 15µm), connective tissue (TVT a, 37 µm; b, 36 µm; c, 43 µm; d, 41 µm; UltraPro a, 33 µm; b, 32 µm; c, 40 µm; d, 38 µm; PVDF a, 25 µm; b, 22 µm; c, 22 µm; d, 24 µm), and macrophage infiltration (TVT a, 36%; b, 33%; c, 23%; d, 20%; UltraPro a, 34%; b, 28%; c, 25%; d, 22%; PVDF a, 24%; b, 18%; c, 18%; d, 16%) revealed comparable ranking characteristics at every time point after explantation. The in vivo performance of these meshes in a sheep model was predictable with a previously developed in vitro test system. Coating of meshes with autologous plasma prior to implantation seems to have a positive effect on the meshes biocompatibility. CONCLUSION We have applied IDEAL criteria on a new innovation for surgical meshes. The results permit the generation of a ranking of currently available meshes with potential to optimize future meshes.'),\n", - " 0.7255579829216003),\n", - " (Document(metadata={'_id': '18909530', 'title': 'Contractile forces sustain and polarize hematopoiesis from stem and progenitor cells.'}, page_content='Self-renewal and differentiation of stem cells depend on asymmetric division and polarized motility processes that in other cell types are modulated by nonmuscle myosin-II (MII) forces and matrix mechanics. Here, mass spectrometry-calibrated intracellular flow cytometry of human hematopoiesis reveals MIIB to be a major isoform that is strongly polarized in hematopoietic stem cells and progenitors (HSC/Ps) and thereby downregulated in differentiated cells via asymmetric division. MIIA is constitutive and activated by dephosphorylation during cytokine-triggered differentiation of cells grown on stiff, endosteum-like matrix, but not soft, marrow-like matrix. In vivo, MIIB is required for generation of blood, while MIIA is required for sustained HSC/P engraftment. Reversible inhibition of both isoforms in culture with blebbistatin enriches for long-term hematopoietic multilineage reconstituting cells by 5-fold or more as assessed in vivo. Megakaryocytes also become more polyploid, producing 4-fold more platelets. MII is thus a multifunctional node in polarized division and niche sensing.'),\n", - " 0.7254542708396912)]" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector_search(\"0-dimensional biomaterials show inductive properties\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "8fdjA-VQRav-" - }, - "source": [ - "### Hybrid Search LangChain<>MongoDB Integration" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "ReA2Jpbntzmk" - }, - "outputs": [], - "source": [ - "from langchain_mongodb.retrievers import MongoDBAtlasHybridSearchRetriever\n", - "\n", - "def hybrid_search(query: str, top_k: int = 10) -> List[Document]:\n", - " hybrid_search = MongoDBAtlasHybridSearchRetriever(\n", - " vectorstore=vector_store,\n", - " search_index_name=\"text_search_index\",\n", - " top_k=top_k\n", - " )\n", - " return hybrid_search.get_relevant_documents(query)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "mJ0Fa-6tuAoM", - "outputId": "8b0110de-e499-4e1d-eae4-1520d9c5b286" - }, - "outputs": [ - { - "data": { - "text/plain": [ - "[Document(metadata={'_id': '4346436', 'title': 'Nonlinear Elasticity in Biological Gels', 'vector_score': 0.01639344262295082, 'rank': 0, 'fulltext_score': 0, 'score': 0.01639344262295082}, page_content='Unlike most synthetic materials, biological materials often stiffen as they are deformed. This nonlinear elastic response, critical for the physiological function of some tissues, has been documented since at least the 19th century, but the molecular structure and the design principles responsible for it are unknown. Current models for this response require geometrically complex ordered structures unique to each material. In this Article we show that a much simpler molecular theory accounts for strain stiffening in a wide range of molecularly distinct biopolymer gels formed from purified cytoskeletal and extracellular proteins. This theory shows that systems of semi-flexible chains such as filamentous proteins arranged in an open crosslinked meshwork invariably stiffen at low strains without the need for a specific architecture or multiple elements with different intrinsic stiffnesses.'),\n", - " Document(metadata={'_id': '10608397', 'title': 'High-performance neuroprosthetic control by an individual with tetraplegia.', 'score': 0.01639344262295082, 'fulltext_score': 0.01639344262295082, 'rank': 0, 'vector_score': 0}, page_content=\"BACKGROUND Paralysis or amputation of an arm results in the loss of the ability to orient the hand and grasp, manipulate, and carry objects, functions that are essential for activities of daily living. Brain-machine interfaces could provide a solution to restoring many of these lost functions. We therefore tested whether an individual with tetraplegia could rapidly achieve neurological control of a high-performance prosthetic limb using this type of an interface. METHODS We implanted two 96-channel intracortical microelectrodes in the motor cortex of a 52-year-old individual with tetraplegia. Brain-machine-interface training was done for 13 weeks with the goal of controlling an anthropomorphic prosthetic limb with seven degrees of freedom (three-dimensional translation, three-dimensional orientation, one-dimensional grasping). The participant's ability to control the prosthetic limb was assessed with clinical measures of upper limb function. This study is registered with ClinicalTrials.gov, NCT01364480. FINDINGS The participant was able to move the prosthetic limb freely in the three-dimensional workspace on the second day of training. After 13 weeks, robust seven-dimensional movements were performed routinely. Mean success rate on target-based reaching tasks was 91·6% (SD 4·4) versus median chance level 6·2% (95% CI 2·0-15·3). Improvements were seen in completion time (decreased from a mean of 148 s [SD 60] to 112 s [6]) and path efficiency (increased from 0·30 [0·04] to 0·38 [0·02]). The participant was also able to use the prosthetic limb to do skilful and coordinated reach and grasp movements that resulted in clinically significant gains in tests of upper limb function. No adverse events were reported. INTERPRETATION With continued development of neuroprosthetic limbs, individuals with long-term paralysis could recover the natural and intuitive command signals for hand placement, orientation, and reaching, allowing them to perform activities of daily living. FUNDING Defense Advanced Research Projects Agency, National Institutes of Health, Department of Veterans Affairs, and UPMC Rehabilitation Institute.\"),\n", - " Document(metadata={'_id': '40212412', 'title': 'Periosteal bone formation--a neglected determinant of bone strength.', 'score': 0.016129032258064516, 'fulltext_score': 0.016129032258064516, 'rank': 1, 'vector_score': 0}, page_content=\"Life forms that have low body mass can hunt for food on the undersurface of branches or along shear cliff faces quite unperturbed by gravity. For larger animals, the hunt for dinner and the struggle to avoid becoming someone else's meal require rapid movement against gravity. This need is met by the lever function of long bones, three-dimensional masterpieces of biomechanical engineering that, by their material composition and structural design, achieve the contradictory properties of stiffness and flexibility, strength and lightness.1 Material stiffness results from the encrusting of the triple-helical structure of collagen type I with hydroxyapatite crystals, which confers . . .\"),\n", - " Document(metadata={'_id': '927561', 'title': 'Emergent structures and dynamics of cell colonies by contact inhibition of locomotion', 'vector_score': 0.016129032258064516, 'rank': 1, 'fulltext_score': 0, 'score': 0.016129032258064516}, page_content='Cells in tissues can organize into a broad spectrum of structures according to their function. Drastic changes of organization, such as epithelial-mesenchymal transitions or the formation of spheroidal aggregates, are often associated either to tissue morphogenesis or to cancer progression. Here, we study the organization of cell colonies by means of simulations of self-propelled particles with generic cell-like interactions. The interplay between cell softness, cell-cell adhesion, and contact inhibition of locomotion (CIL) yields structures and collective dynamics observed in several existing tissue phenotypes. These include regular distributions of cells, dynamic cell clusters, gel-like networks, collectively migrating monolayers, and 3D aggregates. We give analytical predictions for transitions between noncohesive, cohesive, and 3D cell arrangements. We explicitly show how CIL yields an effective repulsion that promotes cell dispersal, thereby hindering the formation of cohesive tissues. Yet, in continuous monolayers, CIL leads to collective cell motion, ensures tensile intercellular stresses, and opposes cell extrusion. Thus, our work highlights the prominent role of CIL in determining the emergent structures and dynamics of cell colonies.'),\n", - " Document(metadata={'_id': '43385013', 'title': 'Epithelial and mesenchymal subpopulations within normal basal breast cell lines exhibit distinct stem cell/progenitor properties.', 'score': 0.015873015873015872, 'fulltext_score': 0.015873015873015872, 'rank': 2, 'vector_score': 0}, page_content='It has been proposed that epithelial-mesenchymal transition (EMT) in mammary epithelial cells and breast cancer cells generates stem cell features, and that the presence of EMT characteristics in claudin-low breast tumors reveals their origin in basal stem cells. It remains to be determined, however, whether EMT is an inherent property of normal basal stem cells, and if the presence of a mesenchymal-like phenotype is required for the maintenance of all their stem cell properties. We used nontumorigenic basal cell lines as models of normal stem cells/progenitors and demonstrate that these cell lines contain an epithelial subpopulation (\"EpCAM+,\" epithelial cell adhesion molecule positive [EpCAM(pos)]/CD49f(high)) that spontaneously generates mesenchymal-like cells (\"Fibros,\" EpCAM(neg)/CD49f(med/low)) through EMT. Importantly, stem cell/progenitor properties such as regenerative potential, high aldehyde dehydrogenase 1 activity, and formation of three-dimensional acini-like structures predominantly reside within EpCAM+ cells, while Fibros exhibit invasive behavior and mammosphere-forming ability. A gene expression profiling meta-analysis established that EpCAM+ cells show a luminal progenitor-like expression pattern, while Fibros most closely resemble stromal fibroblasts but not stem cells. Moreover, Fibros exhibit partial myoepithelial traits and strong similarities with claudin-low breast cancer cells. Finally, we demonstrate that Slug and Zeb1 EMT-inducers control the progenitor and mesenchymal-like phenotype in EpCAM+ cells and Fibros, respectively, by inhibiting luminal differentiation. In conclusion, nontumorigenic basal cell lines have intrinsic capacity for EMT, but a mesenchymal-like phenotype does not correlate with the acquisition of global stem cell/progenitor features. Based on our findings, we propose that EMT in normal basal cells and claudin-low breast cancers reflects aberrant/incomplete myoepithelial differentiation.'),\n", - " Document(metadata={'_id': '19685306', 'title': 'Orientationally invariant indices of axon diameter and density from diffusion MRI.', 'vector_score': 0.015873015873015872, 'rank': 2, 'fulltext_score': 0, 'score': 0.015873015873015872}, page_content='This paper proposes and tests a technique for imaging orientationally invariant indices of axon diameter and density in white matter using diffusion magnetic resonance imaging. Such indices potentially provide more specific markers of white matter microstructure than standard indices from diffusion tensor imaging. Orientational invariance allows for combination with tractography and presents new opportunities for mapping brain connectivity and quantifying disease processes. The technique uses a four-compartment tissue model combined with an optimized multishell high-angular-resolution pulsed-gradient-spin-echo acquisition. We test the method in simulation, on fixed monkey brains using a preclinical scanner and on live human brains using a clinical 3T scanner. The human data take about one hour to acquire. The simulation experiments show that both monkey and human protocols distinguish distributions of axon diameters that occur naturally in white matter. We compare the axon diameter index with the mean axon diameter weighted by axon volume. The index differs from this mean and is protocol dependent, but correlation is good for the monkey protocol and weaker, but discernible, for the human protocol where greater diffusivity and lower gradient strength limit sensitivity to only the largest axons. Maps of axon diameter and density indices from the monkey and human data in the corpus callosum and corticospinal tract reflect known trends from histology. The results show orientationally invariant sensitivity to natural axon diameter distributions for the first time with both specialist and clinical hardware. This demonstration motivates further refinement, validation, and evaluation of the precise nature of the indices and the influence of potential confounds.'),\n", - " Document(metadata={'_id': '17388232', 'title': 'Mechanical regulation of cell function with geometrically modulated elastomeric substrates', 'vector_score': 0.015625, 'rank': 3, 'fulltext_score': 0, 'score': 0.015625}, page_content='We report the establishment of a library of micromolded elastomeric micropost arrays to modulate substrate rigidity independently of effects on adhesive and other material surface properties. We demonstrated that micropost rigidity impacts cell morphology, focal adhesions, cytoskeletal contractility and stem cell differentiation. Furthermore, early changes in cytoskeletal contractility predicted later stem cell fate decisions in single cells.'),\n", - " Document(metadata={'_id': '10931595', 'title': 'Geometry, epistasis, and developmental patterning.', 'score': 0.015625, 'fulltext_score': 0.015625, 'rank': 3, 'vector_score': 0}, page_content='Developmental signaling networks are composed of dozens of components whose interactions are very difficult to quantify in an embryo. Geometric reasoning enumerates a discrete hierarchy of phenotypic models with a few composite variables whose parameters may be defined by in vivo data. Vulval development in the nematode Caenorhabditis elegans is a classic model for the integration of two signaling pathways; induction by EGF and lateral signaling through Notch. Existing data for the relative probabilities of the three possible terminal cell types in diverse genetic backgrounds as well as timed ablation of the inductive signal favor one geometric model and suffice to fit most of its parameters. The model is fully dynamic and encompasses both signaling and commitment. It then predicts the correlated cell fate probabilities for a cross between any two backgrounds/conditions. The two signaling pathways are combined additively, without interactions, and epistasis only arises from the nonlinear dynamical flow in the landscape defined by the geometric model. In this way, the model quantitatively fits genetic experiments purporting to show mutual pathway repression. The model quantifies the contributions of extrinsic vs. intrinsic sources of noise in the penetrance of mutant phenotypes in signaling hypomorphs and explains available experiments with no additional parameters. Data for anchor cell ablation fix the parameters needed to define Notch autocrine signaling.'),\n", - " Document(metadata={'_id': '27049238', 'title': 'Large deformation of red blood cell ghosts in a simple shear flow.', 'score': 0.015384615384615385, 'fulltext_score': 0.015384615384615385, 'rank': 4, 'vector_score': 0}, page_content='Red blood cells are known to change shape in response to local flow conditions. Deformability affects red blood cell physiological function and the hydrodynamic properties of blood. The immersed boundary method is used to simulate three-dimensional membrane-fluid flow interactions for cells with the same internal and external fluid viscosities. The method has been validated for small deformations of an initially spherical capsule in simple shear flow for both neo-Hookean and the Evans-Skalak membrane models. Initially oblate spheroidal capsules are simulated and it is shown that the red blood cell membrane exhibits asymptotic behavior as the ratio of the dilation modulus to the extensional modulus is increased and a good approximation of local area conservation is obtained. Tank treading behavior is observed and its period calculated.'),\n", - " Document(metadata={'_id': '14082855', 'title': 'Inflammatory Reaction as Determinant of Foreign Body Reaction Is an Early and Susceptible Event after Mesh Implantation', 'vector_score': 0.015384615384615385, 'rank': 4, 'fulltext_score': 0, 'score': 0.015384615384615385}, page_content='PURPOSE To investigate and relate the ultrashort-term and long-term courses of determinants for foreign body reaction as biocompatibility predictors for meshes in an animal model. MATERIALS AND METHODS Three different meshes (TVT, UltraPro, and PVDF) were implanted in sheep. Native and plasma coated meshes were placed bilaterally: (a) interaperitoneally, (b) as fascia onlay, and (c) as muscle onlay (fascia sublay). At 5 min, 20 min, 60 min, and 120 min meshes were explanted and histochemically investigated for inflammatory infiltrate, macrophage infiltration, vessel formation, myofibroblast invasion, and connective tissue accumulation. The results were related to long-term values over 24 months. RESULTS Macrophage invasion reached highest extents with up to 60% in short-term and decreased within 24 months to about 30%. Inflammatory infiltrate increased within the first 2 hours, the reached levels and the different extents and ranking among the investigated meshes remained stable during long-term follow up. For myofibroblasts, connective tissue, and CD31+ cells, no activity was detected during the first 120 min. CONCLUSION The local inflammatory reaction is an early and susceptible event after mesh implantation. It cannot be influenced by prior plasma coating and does not depend on the localisation of implantation.')]" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "hybrid_search(\"0-dimensional biomaterials show inductive properties\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "28LA_rDCToLz" - }, - "source": [ - "# Information Retrieval Evaluation Process Begins\n", - "\n", - "\n", - "---\n", - "\n", - "\n", - "\n", - "---\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "W4n7ELsGxWVV" - }, - "source": [ - "# **Step 6: Custom Retrieval Class For Lexical Search**\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Y9IcUtnRvGrx" - }, - "outputs": [], - "source": [ - "from beir.retrieval.search.base import BaseSearch\n", - "from langchain_mongodb.retrievers import MongoDBAtlasFullTextSearchRetriever\n", - "from typing import Dict\n", - "from beir.retrieval.evaluation import EvaluateRetrieval\n", - "\n", - "class MongoDBSearch(BaseSearch):\n", - " def __init__(self, collection, search_index_name, search_field=\"text\", batch_size=128):\n", - " self.collection = collection\n", - " self.search_index_name = search_index_name\n", - " self.search_field = search_field\n", - " self.batch_size = batch_size\n", - "\n", - " def search(self,\n", - " corpus: Dict[str, Dict[str, str]],\n", - " queries: Dict[str, str],\n", - " top_k: int,\n", - " score_function: str = \"dot\",\n", - " **kwargs) -> Dict[str, Dict[str, float]]:\n", - " results = {}\n", - " for query_id, query_text in queries.items():\n", - " full_text_search = MongoDBAtlasFullTextSearchRetriever(\n", - " collection=self.collection,\n", - " search_index_name=self.search_index_name,\n", - " search_field=self.search_field,\n", - " top_k=top_k\n", - " )\n", - " documents = full_text_search.get_relevant_documents(query_text)\n", - " results[query_id] = {doc.metadata['_id']: doc.metadata['score'] for doc in documents}\n", - " return results" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "OAhWdRiFx2QD" - }, - "outputs": [], - "source": [ - "model = MongoDBSearch(db[CORPUS_COLLECTION_NAME], TEXT_SEARCH_INDEX)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "ETzC-2k5zAwl" - }, - "outputs": [], - "source": [ - "retriever = EvaluateRetrieval(model)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "j7a_ORZJvG1h" - }, - "outputs": [], - "source": [ - "# Retrieve results\n", - "results = retriever.retrieve(corpus, queries)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "KvPjPmI3DxMV", - "outputId": "d12aa9fd-1a7a-4e87-b5db-9f31e7916248" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sample of retrieved results:\n", - "Query ID: 1\n", - "Query text: 0-dimensional biomaterials show inductive properties.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 10608397, Score: 6.045361518859863\n", - " Doc ID: 40212412, Score: 4.411067962646484\n", - " Doc ID: 43385013, Score: 4.344019412994385\n", - "\n", - "Query ID: 3\n", - "Query text: 1,000 genomes project enables mapping of genetic sequence variation consisting of rare variants with larger penetrance effects than common variants.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 3672261, Score: 14.99349308013916\n", - " Doc ID: 14717500, Score: 13.623835563659668\n", - " Doc ID: 23389795, Score: 13.595733642578125\n", - "\n", - "Query ID: 5\n", - "Query text: 1/2000 in UK have abnormal PrP positivity.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 13734012, Score: 9.427136421203613\n", - " Doc ID: 18617259, Score: 7.08165979385376\n", - " Doc ID: 42240424, Score: 5.731115818023682\n", - "\n", - "Query ID: 13\n", - "Query text: 5% of perinatal mortality is due to low birth weight.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 1263446, Score: 9.440444946289062\n", - " Doc ID: 17450673, Score: 9.43663501739502\n", - " Doc ID: 7662395, Score: 9.31999397277832\n", - "\n", - "Query ID: 36\n", - "Query text: A deficiency of vitamin B12 increases blood levels of homocysteine.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 42441846, Score: 13.356172561645508\n", - " Doc ID: 33409100, Score: 10.587646484375\n", - " Doc ID: 18557974, Score: 10.070034980773926\n", - "\n" - ] - } - ], - "source": [ - "# Print some results for inspection\n", - "print(\"Sample of retrieved results:\")\n", - "for query_id, doc_scores in list(results.items())[:5]: # First 5 queries\n", - " print(f\"Query ID: {query_id}\")\n", - " print(f\"Query text: {queries[query_id]}\")\n", - " print(\"Top 3 retrieved documents:\")\n", - " for doc_id, score in list(doc_scores.items())[:3]:\n", - " print(f\" Doc ID: {doc_id}, Score: {score}\")\n", - " print()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "6_du_owvD2r5" - }, - "outputs": [], - "source": [ - "# Evaluate the model\n", - "metrics = retriever.evaluate(qrels, results, retriever.k_values)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "-bLj2_NnEtZ_", - "outputId": "22302b4e-d1a0-44c4-8d35-ea0633b51af1" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "NDCG:\n", - " NDCG@1: 0.5300\n", - " NDCG@3: 0.6123\n", - " NDCG@5: 0.6322\n", - " NDCG@10: 0.6506\n", - " NDCG@100: 0.6749\n", - " NDCG@1000: 0.6860\n", - "\n", - "MAP:\n", - " MAP@1: 0.5115\n", - " MAP@3: 0.5854\n", - " MAP@5: 0.5979\n", - " MAP@10: 0.6071\n", - " MAP@100: 0.6124\n", - " MAP@1000: 0.6129\n", - "\n", - "Recall:\n", - " Recall@1: 0.5115\n", - " Recall@3: 0.6673\n", - " Recall@5: 0.7151\n", - " Recall@10: 0.7676\n", - " Recall@100: 0.8752\n", - " Recall@1000: 0.9617\n", - "\n", - "Precision:\n", - " P@1: 0.5300\n", - " P@3: 0.2367\n", - " P@5: 0.1547\n", - " P@10: 0.0847\n", - " P@100: 0.0099\n", - " P@1000: 0.0011\n" - ] - } - ], - "source": [ - "ndcg, _map, recall, precision = metrics\n", - "\n", - "lexical_search_metric_dicts = [ndcg, _map, recall, precision]\n", - "\n", - "for name, metric_dict in zip(metric_names, lexical_search_metric_dicts):\n", - " print(f\"\\n{name}:\")\n", - " for k, score in metric_dict.items():\n", - " print(f\" {k}: {score:.4f}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "rQZAvU1Oxzxe" - }, - "source": [ - "# **Step 7: Custom Retrieval Class For Vector Search**\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "hNSDBi1yx3v2" - }, - "outputs": [], - "source": [ - "class MongoDBVectorSearch(BaseSearch):\n", - " def __init__(self, vector_store: MongoDBAtlasVectorSearch, embedding_model: OpenAIEmbeddings, batch_size=128):\n", - " self.vector_store = vector_store\n", - " self.embedding_model = embedding_model\n", - " self.batch_size = batch_size\n", - "\n", - " def search(self,\n", - " corpus: Dict[str, Dict[str, str]],\n", - " queries: Dict[str, str],\n", - " top_k: int,\n", - " score_function: str = \"dot\",\n", - " **kwargs) -> Dict[str, Dict[str, float]]:\n", - " results = {}\n", - " for query_id, query_text in queries.items():\n", - " vector_results = self.vector_store.similarity_search_with_score(query=query_text, k=top_k)\n", - " # Convert to the format expected by BEIR\n", - " results[query_id] = {str(doc.metadata.get('_id', i)): score for i, (doc, score) in enumerate(vector_results)}\n", - " return results" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "4eSbP11Gx-__" - }, - "outputs": [], - "source": [ - "mongodb_vector_search = MongoDBVectorSearch(vector_store, embedding_model)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "cUf0-vhlyA53" - }, - "outputs": [], - "source": [ - "vector_search_retriever = EvaluateRetrieval(mongodb_vector_search)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "k9YFG61zyEox" - }, - "outputs": [], - "source": [ - "vector_search_eval_results = vector_search_retriever.retrieve(corpus, queries)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "S6VnMRLQikgt", - "outputId": "1394db41-8473-498d-db55-c0a6d63b8135" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sample of retrieved results:\n", - "Query ID: 1\n", - "Query text: 0-dimensional biomaterials show inductive properties.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 4346436, Score: 0.755730390548706\n", - " Doc ID: 14082855, Score: 0.7475494146347046\n", - " Doc ID: 927561, Score: 0.7456868886947632\n", - "\n", - "Query ID: 3\n", - "Query text: 1,000 genomes project enables mapping of genetic sequence variation consisting of rare variants with larger penetrance effects than common variants.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 2739854, Score: 0.8083912134170532\n", - " Doc ID: 41782935, Score: 0.8060566782951355\n", - " Doc ID: 1388704, Score: 0.8057119846343994\n", - "\n", - "Query ID: 5\n", - "Query text: 1/2000 in UK have abnormal PrP positivity.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 13734012, Score: 0.8474858999252319\n", - " Doc ID: 18617259, Score: 0.8069760799407959\n", - " Doc ID: 21550246, Score: 0.8011995553970337\n", - "\n", - "Query ID: 13\n", - "Query text: 5% of perinatal mortality is due to low birth weight.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 1263446, Score: 0.7953510284423828\n", - " Doc ID: 26611834, Score: 0.7630125880241394\n", - " Doc ID: 4791384, Score: 0.74913090467453\n", - "\n", - "Query ID: 36\n", - "Query text: A deficiency of vitamin B12 increases blood levels of homocysteine.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 16252863, Score: 0.8435379266738892\n", - " Doc ID: 18557974, Score: 0.8112655282020569\n", - " Doc ID: 3215494, Score: 0.8056871891021729\n", - "\n" - ] - } - ], - "source": [ - "print(\"Sample of retrieved results:\")\n", - "for query_id, doc_scores in list(vector_search_eval_results.items())[:5]: # First 5 queries\n", - " print(f\"Query ID: {query_id}\")\n", - " print(f\"Query text: {queries[query_id]}\")\n", - " print(\"Top 3 retrieved documents:\")\n", - " for doc_id, score in list(doc_scores.items())[:3]:\n", - " print(f\" Doc ID: {doc_id}, Score: {score}\")\n", - " print()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "nxQBuZEWimsy" - }, - "outputs": [], - "source": [ - "ndcg, _map, recall, precision = vector_search_retriever.evaluate(qrels, vector_search_eval_results, vector_search_retriever.k_values)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "FQjtEA49zoew", - "outputId": "6b9c9835-a0ea-4c58-974c-896f4b4b5f1b" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "NDCG:\n", - " NDCG@1: 0.5800\n", - " NDCG@3: 0.6430\n", - " NDCG@5: 0.6690\n", - " NDCG@10: 0.6920\n", - " NDCG@100: 0.7202\n", - " NDCG@1000: 0.7265\n", - "\n", - "MAP:\n", - " MAP@1: 0.5532\n", - " MAP@3: 0.6165\n", - " MAP@5: 0.6349\n", - " MAP@10: 0.6460\n", - " MAP@100: 0.6529\n", - " MAP@1000: 0.6532\n", - "\n", - "Recall:\n", - " Recall@1: 0.5532\n", - " Recall@3: 0.6885\n", - " Recall@5: 0.7530\n", - " Recall@10: 0.8198\n", - " Recall@100: 0.9450\n", - " Recall@1000: 0.9933\n", - "\n", - "Precision:\n", - " P@1: 0.5800\n", - " P@3: 0.2489\n", - " P@5: 0.1680\n", - " P@10: 0.0930\n", - " P@100: 0.0107\n", - " P@1000: 0.0011\n" - ] - } - ], - "source": [ - "vector_search_metric_dicts = [ndcg, _map, recall, precision]\n", - "\n", - "for name, metric_dict in zip(metric_names, vector_search_metric_dicts):\n", - " print(f\"\\n{name}:\")\n", - " for k, score in metric_dict.items():\n", - " print(f\" {k}: {score:.4f}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "ekUcNjn0xpRz" - }, - "source": [ - "# **Step 8: Custom Retrieval Class For Hybrid Search**\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "ZutxbNWXxrWt" - }, - "outputs": [], - "source": [ - "class MongoDBHybridSearch(BaseSearch):\n", - " def __init__(self, vector_store: MongoDBAtlasVectorSearch, search_index_name: str, batch_size=128):\n", - " self.vector_store = vector_store\n", - " self.search_index_name = search_index_name\n", - " self.batch_size = batch_size\n", - "\n", - " def search(self,\n", - " corpus: Dict[str, Dict[str, str]],\n", - " queries: Dict[str, str],\n", - " top_k: int,\n", - " score_function: str = \"dot\",\n", - " **kwargs) -> Dict[str, Dict[str, float]]:\n", - " results = {}\n", - " for query_id, query_text in queries.items():\n", - " hybrid_search = MongoDBAtlasHybridSearchRetriever(\n", - " vectorstore=self.vector_store,\n", - " search_index_name=self.search_index_name,\n", - " top_k=top_k\n", - " )\n", - " documents = hybrid_search.get_relevant_documents(query_text)\n", - "\n", - " # Convert to the format expected by BEIR\n", - " # Higher rank (lower index) gets a higher score\n", - " results[query_id] = {self._get_doc_id(doc): (len(documents) - i) / len(documents)\n", - " for i, doc in enumerate(documents)}\n", - "\n", - " return results\n", - "\n", - " def _get_doc_id(self, doc: Document) -> str:\n", - " # Attempt to get the document ID from metadata, fallback to content hash if not available\n", - " return str(doc.metadata.get('_id', hash(doc.page_content)))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "bWxs7qXPxree" - }, - "outputs": [], - "source": [ - "mongodb_hybrid_search = MongoDBHybridSearch(\n", - " vector_store=vector_store,\n", - " search_index_name=\"text_search_index\"\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "edM_DMC1xrgt" - }, - "outputs": [], - "source": [ - "hybrid_search_retriever = EvaluateRetrieval(mongodb_hybrid_search)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Clj7uIv-yL6B" - }, - "outputs": [], - "source": [ - "hybrid_search_results = hybrid_search_retriever.retrieve(corpus, queries)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "_Jqjx3LWySFt", - "outputId": "a49b5943-d4f6-4d03-93fd-be95fb74e880" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sample of retrieved results:\n", - "Query ID: 1\n", - "Query text: 0-dimensional biomaterials show inductive properties.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 10906636, Score: 1.0\n", - " Doc ID: 43385013, Score: 0.999\n", - " Doc ID: 10931595, Score: 0.998\n", - "\n", - "Query ID: 3\n", - "Query text: 1,000 genomes project enables mapping of genetic sequence variation consisting of rare variants with larger penetrance effects than common variants.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 2739854, Score: 1.0\n", - " Doc ID: 23389795, Score: 0.999\n", - " Doc ID: 14717500, Score: 0.998\n", - "\n", - "Query ID: 5\n", - "Query text: 1/2000 in UK have abnormal PrP positivity.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 13734012, Score: 1.0\n", - " Doc ID: 18617259, Score: 0.999\n", - " Doc ID: 17333231, Score: 0.998\n", - "\n", - "Query ID: 13\n", - "Query text: 5% of perinatal mortality is due to low birth weight.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 1263446, Score: 1.0\n", - " Doc ID: 7662395, Score: 0.999\n", - " Doc ID: 30786800, Score: 0.998\n", - "\n", - "Query ID: 36\n", - "Query text: A deficiency of vitamin B12 increases blood levels of homocysteine.\n", - "Top 3 retrieved documents:\n", - " Doc ID: 16252863, Score: 1.0\n", - " Doc ID: 18557974, Score: 0.999\n", - " Doc ID: 33409100, Score: 0.998\n", - "\n" - ] - } - ], - "source": [ - "print(\"Sample of retrieved results:\")\n", - "for query_id, doc_scores in list(hybrid_search_results.items())[:5]:\n", - " print(f\"Query ID: {query_id}\")\n", - " print(f\"Query text: {queries[query_id]}\")\n", - " print(\"Top 3 retrieved documents:\")\n", - " for doc_id, score in list(doc_scores.items())[:3]:\n", - " print(f\" Doc ID: {doc_id}, Score: {score}\")\n", - " print()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "lGkJumGQyM7z" - }, - "outputs": [], - "source": [ - "ndcg, _map, recall, precision = hybrid_search_retriever.evaluate(qrels, hybrid_search_results, hybrid_search_retriever.k_values)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "V0yGPOLCybEb", - "outputId": "36c5eb5d-28fc-4e92-e3fb-da01dc1dbda3" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "NDCG:\n", - " NDCG@1: 0.5933\n", - " NDCG@3: 0.6739\n", - " NDCG@5: 0.6903\n", - " NDCG@10: 0.7128\n", - " NDCG@100: 0.7423\n", - " NDCG@1000: 0.7473\n", - "\n", - "MAP:\n", - " MAP@1: 0.5693\n", - " MAP@3: 0.6464\n", - " MAP@5: 0.6582\n", - " MAP@10: 0.6695\n", - " MAP@100: 0.6765\n", - " MAP@1000: 0.6767\n", - "\n", - "Recall:\n", - " Recall@1: 0.5693\n", - " Recall@3: 0.7262\n", - " Recall@5: 0.7657\n", - " Recall@10: 0.8297\n", - " Recall@100: 0.9600\n", - " Recall@1000: 0.9967\n", - "\n", - "Precision:\n", - " P@1: 0.5933\n", - " P@3: 0.2600\n", - " P@5: 0.1680\n", - " P@10: 0.0930\n", - " P@100: 0.0109\n", - " P@1000: 0.0011\n" - ] - } - ], - "source": [ - "hybrid_search_metric_dicts = [ndcg, _map, recall, precision]\n", - "\n", - "for name, metric_dict in zip(metric_names, hybrid_search_metric_dicts):\n", - " print(f\"\\n{name}:\")\n", - " for k, score in metric_dict.items():\n", - " print(f\" {k}: {score:.4f}\")" - ] + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "oB0TFkwoNsv7" + }, + "source": [ + "# Information Retrieval Evaluation With BEIR Benchmark and LangChain and MongoDB\n", + "\n", + "\n", + "---\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "TScxhzzCoi9q" + }, + "source": [ + "# **Step 1: Install Libraires and Set Environment Variables**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "PqqPt3h_UbeG" + }, + "outputs": [], + "source": [ + "!pip install -q openai pymongo langchain langchain_mongodb langchain_openai beir" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Bs3Safw_Uj00", + "outputId": "5644eb4e-1132-483c-a8ac-b8fce85da591" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter OpenAI API Key: ··········\n" + ] + } + ], + "source": [ + "import getpass\n", + "import os\n", + "\n", + "OPENAI_API_KEY = getpass.getpass(\"Enter OpenAI API Key: \")\n", + "os.environ[\"OPENAI_API_KEY\"] = OPENAI_API_KEY\n", + "\n", + "GPT_MODEL = \"gpt-4o-2024-08-06\"\n", + "\n", + "# Areas for optimisation of RAG Pipelines associated with chunking strategy\n", + "EMBEDDING_MODEL = \"text-embedding-3-small\"\n", + "EMBEDDING_DIMENSION_SIZE = 256" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "g0GJ9efPUtfA", + "outputId": "1bc3addc-a31e-4a16-9dba-d3486679a419" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter MongoDB URI: ··········\n" + ] + } + ], + "source": [ + "MONGO_URI = getpass.getpass(\"Enter MongoDB URI: \")\n", + "os.environ[\"MONGO_URI\"] = MONGO_URI" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "qa2Bn-N-pp9a" + }, + "outputs": [], + "source": [ + "metric_names = [\"NDCG\", \"MAP\", \"Recall\", \"Precision\"]\n", + "information_retrieval_search_methods = ['Lexical', 'Vector', 'Hybrid']" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "rn4FIfvSo33q" + }, + "source": [ + "# **Step 2: Data Loading**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "jMYkRQwiVag2", + "outputId": "e26784b4-e0fe-48d4-b8e3-9bff5a0c3ad0" + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.10/dist-packages/beir/util.py:2: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)\n", + " from tqdm.autonotebook import tqdm\n" + ] + } + ], + "source": [ + "from beir import util\n", + "from beir.datasets.data_loader import GenericDataLoader\n", + "from beir.retrieval.evaluation import EvaluateRetrieval\n", + "\n", + "\n", + "# Load BEIR dataset\n", + "def load_beir_dataset(dataset_name=\"scifact\"):\n", + " url = f\"https://public.ukp.informatik.tu-darmstadt.de/thakur/BEIR/datasets/{dataset_name}.zip\"\n", + " data_path = util.download_and_unzip(url, \"datasets\")\n", + " corpus, queries, qrels = GenericDataLoader(data_folder=data_path).load(split=\"test\")\n", + " return corpus, queries, qrels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 81, + "referenced_widgets": [ + "51c3a472109243c681898fb32aeda7d7", + "f22b82b8010a4a79b0b42908966cc89e", + "35b668058eca435a86829f32ca421859", + "84d25add023044d68f383b81dacaf462", + "c3375ea1a272481babcaece7f79b428e", + "6770f34c4be644cda13221e47d00ca28", + "c2c384a4406b4b9f9dfc57779d7246ee", + "33ef6c005a52428cb00a9e7ccb0e6b2c", + "b8c4d550a4fb475d8a66c1e5deefb1f2", + "c45d82a40d2c4096b6c00b6c93290add", + "9cbf8f18e9dd4cd3acc274ad3f4868ae", + "73cddc3fa8bb4495b335018fae3b063e", + "4950b546681b4c8cbec0a9c3acf08c37", + "30ccab778b894d8c86359fb850ee76f2", + "c25ebc49169a4fccae65c84ba71b50c7", + "00135b96c1e34abf94352e5d14dfbfc2", + "350c3f298a7b414c8ab6ea4492fb98c3", + "6275b672934d4cc383cc4c18f3dfe4b7", + "b7df766690574c09b4942e0d27151171", + "e65a397cb2e44371886c3f51362a9bc6", + "7350acfbe3bd4e1cb4ff49290a6cd58f", + "5b4d7df8ac4e4a788d7684f47f1d1b76" + ] + }, + "id": "si-mKb3ozi11", + "outputId": "49973c88-3d9a-485e-ceb5-c80bd4c69330" + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "51c3a472109243c681898fb32aeda7d7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "datasets/scifact.zip: 0%| | 0.00/2.69M [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plot_search_method_comparison(\n", - " lexical_search_metric_dicts,\n", - " vector_search_metric_dicts,\n", - " hybrid_search_metric_dicts,\n", - " metric_names\n", - ")" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "Found 478 documents without embeddings out of 5183 total documents.\n", + "Generating embeddings for documents without them...\n" + ] }, { - "cell_type": "markdown", - "metadata": { - "id": "oeERj6U4oMj9" - }, - "source": [ - "# **Step 10: Storing Evaluation Results In MongoDB**" - ] + "name": "stderr", + "output_type": "stream", + "text": [ + "Embedding documents: 100%|██████████| 478/478 [03:29<00:00, 2.28it/s]" + ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "ELaECcHDoQnI" - }, - "outputs": [], - "source": [ - "from datetime import datetime\n", - "\n", - "def store_evaluation_results(db: Any, search_method: str, metrics: Dict[str, Dict[str, float]], additional_info: Dict[str, Any] = None):\n", - " \"\"\"\n", - " Store evaluation results in MongoDB.\n", - "\n", - " Args\n", - " db: MongoDB database instance\n", - " search_method: Name of the search method (e.g., 'lexical', 'vector', 'hybrid')\n", - " metrics: Dictionary containing evaluation metrics (ndcg, map, recall, precision)\n", - " additional_info: Optional dictionary for any additional information to store\n", - " \"\"\"\n", - " collection = db['evaluation_results']\n", - "\n", - " # Prepare the document to be inserted\n", - " result_doc = {\n", - " \"timestamp\": datetime.utcnow(),\n", - " \"search_method\": search_method,\n", - " \"metrics\": {}\n", - " }\n", - "\n", - " # Add metrics to the document\n", - " for metric_name, metric_values in metrics.items():\n", - " result_doc[\"metrics\"][metric_name] = metric_values\n", - "\n", - " # Add any additional information\n", - " if additional_info:\n", - " result_doc.update(additional_info)\n", - "\n", - " # Insert the document\n", - " insert_result = collection.insert_one(result_doc)\n", - "\n", - " print(f\"Evaluation results for {search_method} stored with ID: {insert_result.inserted_id}\")" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "New embeddings generated and stored successfully.\n", + "Total documents with embeddings: 5183\n" + ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "oMcDhx-9oqQG" - }, - "outputs": [], - "source": [ - "metadata = {\n", - " \"dataset_name\": DATASET,\n", - " \"corpus_size\": len(corpus),\n", - " \"num_queries\": len(queries),\n", - " \"num_qrels\": sum(len(q) for q in qrels.values())\n", - "}\n", - "\n", - "information_retrieval_eval_metrics_list = [\n", - " lexical_search_metric_dicts,\n", - " vector_search_metric_dicts,\n", - " hybrid_search_metric_dicts,\n", - "]\n", - "\n", - "# Iterate through metrics list and store evaluation results\n", - "for search_method, metrics in zip(information_retrieval_search_methods, information_retrieval_eval_metrics_list):\n", - " store_evaluation_results(db, search_method, metrics, metadata)" - ] + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "generate_and_store_embeddings(corpus, db, CORPUS_COLLECTION_NAME)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "H5JDJPQIBouB" + }, + "source": [ + "# **Step 5: Testing Information Retrieval Mechanisms**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "XXRlz-HKrSNH", + "outputId": "116ecda2-84ce-4380-96f2-e83a0fc42ef8" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of documents in scifact_corpus: 5183\n", + "Number of queries in scifact_queries: 300\n", + "Number of relevance judgments in scifact_qrels: 339\n", + "\n", + "Sample document from corpus:\n", + "{'_id': '4983', 'text': 'Alterations of the architecture of cerebral white matter in the developing human brain can affect cortical development and result in functional disabilities. A line scan diffusion-weighted magnetic resonance imaging (MRI) sequence with diffusion tensor analysis was applied to measure the apparent diffusion coefficient, to calculate relative anisotropy, and to delineate three-dimensional fiber architecture in cerebral white matter in preterm (n = 17) and full-term infants (n = 7). To assess effects of prematurity on cerebral white matter development, early gestation preterm infants (n = 10) were studied a second time at term. In the central white matter the mean apparent diffusion coefficient at 28 wk was high, 1.8 microm2/ms, and decreased toward term to 1.2 microm2/ms. In the posterior limb of the internal capsule, the mean apparent diffusion coefficients at both times were similar (1.2 versus 1.1 microm2/ms). Relative anisotropy was higher the closer birth was to term with greater absolute values in the internal capsule than in the central white matter. Preterm infants at term showed higher mean diffusion coefficients in the central white matter (1.4 +/- 0.24 versus 1.15 +/- 0.09 microm2/ms, p = 0.016) and lower relative anisotropy in both areas compared with full-term infants (white matter, 10.9 +/- 0.6 versus 22.9 +/- 3.0%, p = 0.001; internal capsule, 24.0 +/- 4.44 versus 33.1 +/- 0.6% p = 0.006). Nonmyelinated fibers in the corpus callosum were visible by diffusion tensor MRI as early as 28 wk; full-term and preterm infants at term showed marked differences in white matter fiber organization. The data indicate that quantitative assessment of water diffusion by diffusion tensor MRI provides insight into microstructural development in cerebral white matter in living infants.', 'title': 'Microstructural development of human newborn cerebral white matter assessed in vivo by diffusion tensor magnetic resonance imaging.', 'embedding': [0.04606284201145172, 0.08591383695602417, 0.09022205322980881, 0.048893239349126816, -0.06587562710046768, -0.013738700188696384, 0.055606041103601456, 0.002784998621791601, -0.03574316203594208, -0.051347922533750534, 0.033012956380844116, 0.055455755442380905, -0.06297008693218231, 0.012718003243207932, 0.04223053529858589, -0.04864276200532913, 0.0244215726852417, -0.02259308658540249, 0.06602591276168823, 0.01981278322637081, 0.09733562171459198, 0.044159211218357086, -0.054253462702035904, 0.023156659677624702, 0.03376438841223717, -0.07589473575353622, 0.05826110392808914, 0.004818564280867577, -0.01693229004740715, 0.056958623230457306, -0.026024630293250084, -0.014151988551020622, 0.019174065440893173, -0.033789437264204025, -0.06637658178806305, 0.0949811339378357, -0.03336362540721893, 0.02305646985769272, -0.02945617400109768, -0.03140990063548088, -0.008841861970722675, -0.02790321223437786, -0.06717810779809952, 0.02732711285352707, -0.05490470677614212, -0.01709510013461113, -0.03426534682512283, 0.028103593736886978, -0.00209931586869061, 0.11872641742229462, -0.05265040695667267, 0.02152855508029461, 0.004887445364147425, -0.038798991590738297, -0.12774361670017242, 0.023068992421030998, -0.004311346914619207, -0.01922416128218174, -0.039450231939554214, -0.09788667410612106, 0.07614520937204361, 0.011597116477787495, 0.03138485178351402, 0.014089369215071201, -0.022655704990029335, -0.04851752519607544, -0.08486183732748032, 0.0019725116435438395, 0.10289622843265533, -0.0467391312122345, -0.04929400607943535, -0.002121232682839036, 0.041429005563259125, -0.0016938552726060152, -0.09087330102920532, 0.007107303943485022, 0.0032311619725078344, -0.08796776086091995, 0.019449591636657715, 0.06221865117549896, 0.00033207860542461276, -0.03383953124284744, -0.02990703284740448, -0.028153689578175545, -0.051498208194971085, -0.0503460131585598, 0.031359802931547165, -0.022016987204551697, 0.04969476908445358, -0.031234566122293472, 0.03772193565964699, -0.00132596620824188, -0.07995247095823288, 0.06036511808633804, 0.05846148729324341, -0.07113565504550934, -0.012599026784300804, -0.02424623817205429, -0.00929272174835205, 0.0521494522690773, -0.05480451509356499, 0.047991521656513214, 0.0500454381108284, 0.05079687014222145, -0.015930378809571266, -0.05107239633798599, 0.016393763944506645, -0.09182511270046234, -0.08816813677549362, -0.011415519751608372, 0.11231418699026108, 0.0647234320640564, 0.011897689662873745, 0.0854128822684288, 0.016130762174725533, 0.031334757804870605, -0.20428958535194397, -0.12113100290298462, -0.015128850936889648, 0.11221399903297424, 0.0038260463625192642, 0.0976862907409668, 0.0006848998600617051, -0.06988327205181122, 0.07945151627063751, -0.028128642588853836, -0.003635057248175144, -0.012548930943012238, -0.052249640226364136, 0.052850786596536636, 0.08736661076545715, 0.05720910057425499, 0.11111189424991608, -0.04476035758852959, -0.03584335371851921, 0.0332634337246418, 0.025824246928095818, 0.039901092648506165, -0.0533517450094223, -0.009223840199410915, 0.058962441980838776, -0.007983976043760777, 0.21561117470264435, 0.01709510013461113, 0.11802507936954498, 0.05320145562291145, 0.043407779186964035, 0.10590195655822754, 0.06487371772527695, 0.06297008693218231, -0.04152919724583626, 0.09147444367408752, -0.030132463201880455, -0.132452592253685, 0.04909362271428108, 0.02563638985157013, 0.09553218632936478, 0.058211009949445724, -0.027502447366714478, -0.04425940290093422, -0.06542477011680603, 0.05480451509356499, 0.016731908544898033, -0.011640950106084347, 0.07574445009231567, 0.06582552939653397, -0.0824071541428566, -0.01846020482480526, -0.1816464066505432, -0.029681604355573654, 0.012849504128098488, -0.014627896249294281, -0.056658048182725906, 0.007245066575706005, 0.0409030020236969, 0.02181660570204258, -0.039274897426366806, -0.18024373054504395, 0.060465309768915176, -0.03246190771460533, -0.05475441738963127, 0.08100447803735733, -0.01227340567857027, 0.12093061953783035, -0.10990960150957108, 0.0007573035545647144, -0.09022205322980881, 0.11892680078744888, 0.06056550145149231, -0.038222894072532654, 0.03095903992652893, -0.07489282637834549, 0.08536279201507568, -0.02667587250471115, 0.037296123802661896, -0.03995118662714958, 0.11562049388885498, 0.016356192529201508, -0.08726642280817032, 0.010081726126372814, 0.06021483242511749, -0.010037892498075962, -0.06286989152431488, -0.03065846674144268, -0.03373934328556061, 0.04698961228132248, 0.08140524476766586, 0.006719063501805067, -0.0778985545039177, -0.03829803690314293, 0.07384081929922104, -0.009424222633242607, -0.014101892709732056, 0.11211380362510681, -0.1267417073249817, -0.035167064517736435, -0.0839100182056427, -0.025235624983906746, 0.09793677181005478, -0.013851415365934372, -0.05109744518995285, 0.008779242634773254, 0.005053387023508549, 0.13024838268756866, -0.08521250635385513, 0.04992019757628441, 0.014101892709732056, 0.0010747057385742664, -0.022179797291755676, -0.027051588520407677, 0.18425136804580688, 0.05555594712495804, -0.09132415801286697, 0.02060178853571415, 0.019011255353689194, 0.015416900627315044, 0.0016609800513833761, -0.03965061530470848, 0.06297008693218231, -0.04425940290093422, 0.06302018463611603, 0.04786628112196922, -0.024684574455022812, 0.04007642716169357, -0.07935132831335068, 0.0635211393237114, -0.022330084815621376, -0.06392189860343933, -0.044785406440496445, -0.03541754186153412, -0.0262250117957592, -0.1771378070116043, 0.021866699680685997, -0.01402674987912178, -0.04045214504003525, 0.0409030020236969]}\n", + "\n", + "Sample query:\n", + "{'_id': '1', 'text': '0-dimensional biomaterials show inductive properties.'}\n", + "\n", + "Sample relevance judgment:\n", + "{'_id': ObjectId('66e978ed10117d8d102d48b9'), 'query_id': '1', 'doc_id': '31715818', 'relevance': 1}\n" + ] + } + ], + "source": [ + "# You can add this cell to verify that the data was ingested correctly\n", + "print(f\"Number of documents in {CORPUS_COLLECTION_NAME}: {db[CORPUS_COLLECTION_NAME].count_documents({})}\")\n", + "print(f\"Number of queries in {QUERIES_COLLECTION_NAME}: {db[QUERIES_COLLECTION_NAME].count_documents({})}\")\n", + "print(f\"Number of relevance judgments in {QRELS_COLLECTION_NAME}: {db[QRELS_COLLECTION_NAME].count_documents({})}\")\n", + "\n", + "# Display a sample document from each collection\n", + "print(\"\\nSample document from corpus:\")\n", + "print(db[CORPUS_COLLECTION_NAME].find_one())\n", + "print(\"\\nSample query:\")\n", + "print(db[QUERIES_COLLECTION_NAME].find_one())\n", + "print(\"\\nSample relevance judgment:\")\n", + "print(db[QRELS_COLLECTION_NAME].find_one())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "1N4JMyhjCSqr" + }, + "source": [ + "### Full text search MongoDB Aggregation Pipeline Integration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "SdPIeV51CYKA" + }, + "outputs": [], + "source": [ + "def full_text_search_aggregation_pipeline():\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "yiACYciRB8uJ" + }, + "source": [ + "### Full text search with LangChain<>MongoDB Integration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "_a_inIiFAhBo" + }, + "outputs": [], + "source": [ + "# Test lexical search with MongoDB Atlas\n", + "from typing import Any, List, Tuple\n", + "\n", + "from langchain.schema import Document\n", + "from langchain_mongodb.retrievers import MongoDBAtlasFullTextSearchRetriever\n", + "\n", + "\n", + "def full_text_search(collection, query: str, top_k: int = 10) -> List[Document]:\n", + " full_text_search = MongoDBAtlasFullTextSearchRetriever(\n", + " collection=collection,\n", + " search_index_name=TEXT_SEARCH_INDEX,\n", + " search_field=\"text\",\n", + " top_k=top_k\n", + " )\n", + " return full_text_search.get_relevant_documents(query)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "TCaTEr5eBCaL", + "outputId": "07fa1703-0874-4798-bbd5-89c62d9ce9fa" + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + ":13: LangChainDeprecationWarning: The method `BaseRetriever.get_relevant_documents` was deprecated in langchain-core 0.1.46 and will be removed in 1.0. Use :meth:`~invoke` instead.\n", + " return full_text_search.get_relevant_documents(query)\n" + ] + }, + { + "data": { + "text/plain": [ + "[Document(metadata={'_id': '10608397', 'title': 'High-performance neuroprosthetic control by an individual with tetraplegia.', 'embedding': [0.04973480477929115, 0.03962016850709915, 0.039430856704711914, 0.05847017467021942, -0.008748890832066536, -0.015090822242200375, -0.013170663267374039, 0.11856301873922348, 0.07177606225013733, 0.06485266983509064, 0.035752806812524796, -0.035211917012929916, -0.020391540601849556, -0.038754746317863464, 0.09503431618213654, -0.13619601726531982, 0.06528538465499878, -0.10163316875696182, -4.650911796488799e-05, 0.03134455531835556, 0.1062307357788086, -0.06025511026382446, -0.0011722093913704157, -0.03283200412988663, 0.04792282357811928, -0.02377210184931755, 0.008437879383563995, -0.055495280772447586, -0.04043150320649147, 0.01054734829813242, 0.02690926194190979, -0.02799104154109955, -0.09589973837137222, -0.07139743864536285, -0.006781404372304678, 0.022406354546546936, 0.028045129030942917, 0.014374143444001675, -0.02072959765791893, 0.03994470089673996, 0.086001455783844, -0.09708969295024872, 0.0025235884822905064, 0.10974651575088501, -0.055765725672245026, -0.04302777349948883, -0.05495439097285271, 0.004340639803558588, -0.03715911880135536, 0.12548640370368958, -0.03913336619734764, 0.09384436160326004, -0.02708505094051361, 0.06755711883306503, -0.03783523291349411, 0.12018568813800812, 0.016240213066339493, -0.05078953877091408, -0.04805804789066315, 0.04527246579527855, -0.06193186715245247, -0.05400783568620682, 0.056090258061885834, -0.06409543007612228, -0.09243804216384888, 0.020526763051748276, -0.09449342638254166, 0.03840316832065582, 0.005557641386985779, 0.032886091619729996, -0.06571809202432632, 0.06371680647134781, -0.023082466796040535, 0.044569309800863266, -0.10687980055809021, 0.07805038243532181, -0.033913783729076385, 0.06560991704463959, 0.0519254095852375, 0.006835493259131908, -0.05495439097285271, -0.09730605036020279, -0.008863830007612705, 0.007038326933979988, -0.13727779686450958, 0.004482623189687729, -0.05506256967782974, -0.12721724808216095, -0.08562283217906952, -0.06085008755326271, 0.007457516621798277, -0.021513886749744415, -0.046597644686698914, 0.055549368262290955, 0.09005813300609589, -0.1271090805530548, -0.026652337983250618, -0.013799447566270828, 0.050167515873909, 0.0689634308218956, -0.03031686693429947, 0.03710503131151199, 0.03294018283486366, -0.023258255794644356, 0.09844192117452621, 0.021730242297053337, -0.02100004069507122, 0.036564141511917114, 0.05998466536402702, 0.045921534299850464, 0.05619843676686287, -0.029965287074446678, -0.03669936582446098, -0.018295593559741974, 0.09081537276506424, -0.06945023685693741, 0.09470978379249573, -0.08107936382293701, 0.043460484594106674, -0.007890228182077408, -0.03840316832065582, 0.09968596696853638, -0.01898522675037384, -0.10877291113138199, -0.014766287989914417, -0.0935739129781723, 0.008863830007612705, -0.008681279607117176, -0.016551224514842033, -0.1318688988685608, 0.0158480666577816, 0.0950884073972702, 0.10152499377727509, -0.06858480721712112, -0.10568984597921371, 0.09752240777015686, -0.07069428265094757, -0.022135909646749496, -0.07529184222221375, -0.04567813128232956, -0.07610318064689636, -0.03702389821410179, -0.02999233268201351, -0.010811032727360725, -0.07345281541347504, -0.0031320892740041018, 0.14376847445964813, 0.1153176799416542, 0.0016091468278318644, 0.024123679846525192, -0.053980790078639984, 0.0017164795426651835, -0.018511949107050896, 0.03318358212709427, -0.01341406349092722, -0.052899010479450226, -0.08405425399541855, 0.07810446619987488, -0.028937596827745438, -0.12581093609333038, -0.023393478244543076, 0.018457859754562378, 0.06160733476281166, -0.00996589194983244, 0.07312828302383423, 0.14387665688991547, -0.06707032024860382, 0.08735368400812149, -0.10736659914255142, -0.06907161325216293, -0.006142478436231613, -0.06809800863265991, -0.1677839756011963, 0.015293655917048454, 0.03410309553146362, -0.08610963821411133, 0.0851360335946083, 0.011169372126460075, -0.005882175173610449, -0.16215872764587402, -0.08281020820140839, 0.016672924160957336, 0.038619522005319595, 0.08654234558343887, -0.14463390409946442, 0.026408938691020012, -0.07188423722982407, 0.06598854064941406, -0.0415673702955246, 0.003982300404459238, 0.07280375063419342, -2.120773569913581e-05, 0.08740776777267456, 0.03294018283486366, 0.05430532246828079, -0.013035440817475319, 0.1195366159081459, -0.01906636171042919, 0.014306532219052315, -0.10601437836885452, 0.020878341048955917, -0.03134455531835556, 0.009120752103626728, -0.09963187575340271, 0.038835879415273666, -0.034589894115924835, 0.030208688229322433, 0.08021394163370132, -0.014698676764965057, -0.005601588636636734, 0.0018170512048527598, -0.02834261953830719, 0.0746968612074852, -0.01227143406867981, -0.05387261137366295, -0.025908615440130234, 0.00805925577878952, 0.017673570662736893, -0.02530011534690857, -0.026260193437337875, -0.05933559685945511, -0.04143214970827103, 0.031615000218153, 0.06847663223743439, -0.08427061140537262, 0.0054021356627345085, 0.09076128900051117, 0.05373739078640938, 0.029180997982621193, -0.05484621226787567, 0.03934972360730171, -0.003162514418363571, 0.06901752203702927, -0.047706469893455505, 0.01077046524733305, 0.08654234558343887, 0.04397432878613472, -0.01687575876712799, 0.05933559685945511, -0.07085654884576797, 0.10633891075849533, 0.08610963821411133, 0.0718301460146904, -0.05051909387111664, -0.028531929478049278, 0.03139864653348923, -0.05982239916920662, -0.04343344271183014, 0.0023613215889781713, -0.005672580562531948, 0.03780818730592728, -0.028423752635717392, 0.0035259246360510588, 0.011791395023465157, -0.050573185086250305, 0.041702594608068466], 'score': 6.045361518859863}, page_content=\"BACKGROUND Paralysis or amputation of an arm results in the loss of the ability to orient the hand and grasp, manipulate, and carry objects, functions that are essential for activities of daily living. Brain-machine interfaces could provide a solution to restoring many of these lost functions. We therefore tested whether an individual with tetraplegia could rapidly achieve neurological control of a high-performance prosthetic limb using this type of an interface. METHODS We implanted two 96-channel intracortical microelectrodes in the motor cortex of a 52-year-old individual with tetraplegia. Brain-machine-interface training was done for 13 weeks with the goal of controlling an anthropomorphic prosthetic limb with seven degrees of freedom (three-dimensional translation, three-dimensional orientation, one-dimensional grasping). The participant's ability to control the prosthetic limb was assessed with clinical measures of upper limb function. This study is registered with ClinicalTrials.gov, NCT01364480. FINDINGS The participant was able to move the prosthetic limb freely in the three-dimensional workspace on the second day of training. After 13 weeks, robust seven-dimensional movements were performed routinely. Mean success rate on target-based reaching tasks was 91·6% (SD 4·4) versus median chance level 6·2% (95% CI 2·0-15·3). Improvements were seen in completion time (decreased from a mean of 148 s [SD 60] to 112 s [6]) and path efficiency (increased from 0·30 [0·04] to 0·38 [0·02]). The participant was also able to use the prosthetic limb to do skilful and coordinated reach and grasp movements that resulted in clinically significant gains in tests of upper limb function. No adverse events were reported. INTERPRETATION With continued development of neuroprosthetic limbs, individuals with long-term paralysis could recover the natural and intuitive command signals for hand placement, orientation, and reaching, allowing them to perform activities of daily living. FUNDING Defense Advanced Research Projects Agency, National Institutes of Health, Department of Veterans Affairs, and UPMC Rehabilitation Institute.\"),\n", + " Document(metadata={'_id': '40212412', 'title': 'Periosteal bone formation--a neglected determinant of bone strength.', 'embedding': [0.1082371175289154, 0.1280379444360733, 0.1598527580499649, 0.03673721104860306, -0.029200661927461624, 0.13182012736797333, 0.09383145719766617, -0.07575485855340958, 0.017103243619203568, -0.044329386204481125, 0.03173138573765755, -0.04374537244439125, -0.0208993311971426, 0.034067437052726746, 0.04516369104385376, 0.009698791429400444, 0.09772487729787827, -0.0628509446978569, -0.055230963975191116, -0.03242664039134979, 0.044829968363046646, -0.022303743287920952, 0.0075574093498289585, -0.1303739994764328, -0.033956196159124374, 0.0214416291564703, 0.03237101808190346, -0.032927222549915314, -0.0032937650103121996, -0.037905238568782806, 0.01654704101383686, -0.04989141598343849, 0.0054925051517784595, -0.005270024295896292, -0.0731407031416893, 0.043189167976379395, 0.05108725279569626, -0.029089421033859253, 0.10273070633411407, -0.019925974309444427, 0.0005744535010308027, -0.03401181846857071, -0.06435269862413406, 0.028783509507775307, 0.012577141635119915, 0.02053779922425747, -0.009643170982599258, -0.041770849376916885, 0.026072019711136818, 0.1065128892660141, -0.04174304008483887, 0.024584176018834114, 0.07102712988853455, -0.00039064575685188174, -0.033844955265522, 0.0541185587644577, -0.03634786978363991, 0.03403962776064873, -0.027281761169433594, 0.1804322749376297, -0.06618816405534744, -0.06340715289115906, -0.033956196159124374, 0.012883054092526436, -0.07086027413606644, 0.010136800818145275, -0.15473569929599762, 0.031508903950452805, -0.05311739444732666, 0.016449706628918648, -0.06958100199699402, -0.18132220208644867, -0.038683924823999405, 0.0849878266453743, 0.044579677283763885, -0.08648958057165146, -0.003469316754490137, 0.04566427320241928, -0.017881928011775017, 0.03092489019036293, 0.01115882396697998, 0.035096414387226105, -0.10456617921590805, -0.05058667063713074, -0.06351839005947113, -0.052700240164995193, 0.07386376708745956, -0.014558615162968636, -0.13204260170459747, 0.05250557139515877, 0.04502463713288307, -0.09132854640483856, 0.03473488241434097, 0.05481381341814995, 0.014078889973461628, 0.02462589181959629, 0.02500132843852043, 0.034456782042980194, -0.027420811355113983, 0.023916732519865036, -0.007494836580008268, -0.021483343094587326, 0.025599246844649315, -0.11569023877382278, 0.15262211859226227, -0.08621147274971008, 0.006490194704383612, -0.0746980756521225, -0.021080097183585167, -0.0810944065451622, -0.03590290993452072, 0.01231989823281765, -0.06791239231824875, 0.04363413155078888, -0.00911477766931057, -0.04610923305153847, 0.013418398797512054, 0.06324028968811035, 0.0310361310839653, 0.03173138573765755, -0.011687217280268669, 0.11062879115343094, -0.04204895347356796, 0.0007208913448266685, 0.06318467110395432, -0.03860049322247505, 0.04983579367399216, 0.1074584349989891, -0.06807925552129745, -0.08365294337272644, 0.014614235609769821, 0.03904545679688454, 0.04079749435186386, -0.12303212285041809, -0.15228840708732605, 0.007108970545232296, -0.054980672895908356, 0.037543706595897675, 0.06474203616380692, 0.11980614066123962, -0.03723779693245888, 0.023916732519865036, 0.03787742927670479, 0.060514893382787704, 0.045497409999370575, 0.1253681778907776, 0.042660776525735855, 0.07753470540046692, 0.0188691895455122, -0.0015704046236351132, 0.02283213660120964, 0.021094001829624176, -0.030897080898284912, 0.07714536786079407, -0.01252152118831873, -0.04952988401055336, 0.015003577806055546, 0.016505325213074684, -0.02272089570760727, 0.021372102200984955, 0.010880722664296627, -0.012173894792795181, 0.08788008242845535, 0.039712898433208466, -0.020092835649847984, 0.002304766559973359, -0.03632006049156189, -0.06418583542108536, -0.09194036573171616, -0.007995419204235077, 0.054619140923023224, 0.01448909007012844, -0.05283929035067558, 0.0033163607586175203, 0.024820562452077866, -0.009205160662531853, -3.720694439834915e-05, -0.1249232068657875, 0.030897080898284912, -0.08365294337272644, 0.06368525326251984, 0.03815552964806557, 0.01252152118831873, 0.08504345268011093, 0.013814693316817284, 0.10534486174583435, -0.09889290481805801, 0.09182912856340408, 0.021260863170027733, 0.13938449323177338, -0.0029235424008220434, -0.011798457242548466, -0.013654785230755806, -0.07119399309158325, 0.06946976482868195, -0.1191386952996254, 0.08209557086229324, -0.002756681526079774, 0.09316401183605194, 0.05584278702735901, 0.09071671962738037, -0.010171563364565372, -0.0009073062683455646, -0.13604727387428284, 0.013147249817848206, 0.037933047860860825, -0.05662147328257561, 0.056398991495370865, 0.0056732711382210255, -0.038183342665433884, -0.008642004802823067, -0.03595852851867676, 0.07147209346294403, -0.003396315034478903, 0.012007033452391624, -0.01373126357793808, 0.08259615302085876, 0.020217981189489365, -0.07675602287054062, 0.08003762364387512, -0.08098316937685013, -0.0063372389413416386, 0.10095085948705673, 0.16230005025863647, -0.018187839537858963, -0.06479765474796295, 0.07030406594276428, -0.07047092914581299, 0.08103878796100616, -0.005283929407596588, 0.05381264537572861, -0.01835470087826252, 0.06707809120416641, -0.05181031674146652, -0.02708708867430687, -0.011659407056868076, -0.05414636805653572, 0.06318467110395432, 0.08927059173583984, -0.08415352553129196, -0.07987076044082642, 0.016102079302072525, -0.01962006278336048, 0.10389873385429382, -0.03153671324253082, 0.07186143845319748, -0.10829273611307144, 0.01732572540640831, 0.09816984087228775, 0.03423430025577545, 0.03192605450749397, -0.04872338846325874, 0.017603827640414238, -0.03242664039134979, -0.010373187251389027, 0.00214833440259099], 'score': 4.411067962646484}, page_content=\"Life forms that have low body mass can hunt for food on the undersurface of branches or along shear cliff faces quite unperturbed by gravity. For larger animals, the hunt for dinner and the struggle to avoid becoming someone else's meal require rapid movement against gravity. This need is met by the lever function of long bones, three-dimensional masterpieces of biomechanical engineering that, by their material composition and structural design, achieve the contradictory properties of stiffness and flexibility, strength and lightness.1 Material stiffness results from the encrusting of the triple-helical structure of collagen type I with hydroxyapatite crystals, which confers . . .\"),\n", + " Document(metadata={'_id': '43385013', 'title': 'Epithelial and mesenchymal subpopulations within normal basal breast cell lines exhibit distinct stem cell/progenitor properties.', 'embedding': [0.023725250735878944, 0.03393925726413727, 0.12911297380924225, 0.07809252291917801, 0.014056653715670109, 0.019461151212453842, 0.08810819685459137, -0.016610154882073402, -0.029154540970921516, -0.018308358266949654, 0.005516058765351772, -0.05082211643457413, 0.035327568650245667, -0.00568030122667551, -0.008410440757870674, 0.10481751710176468, 0.01672171615064144, -0.04380618408322334, 0.004143242258578539, 0.09405810385942459, 0.09509933739900589, -0.0219526756554842, -0.044525131583213806, -0.07075430452823639, -0.10927994549274445, -0.003600932890549302, -0.00010575028863968328, -0.06703560799360275, -0.015234239399433136, 0.04229391738772392, 0.12177474796772003, -0.0356498546898365, -0.012637353502213955, 0.08186079561710358, -0.12772466242313385, 0.0829516127705574, 0.026774577796459198, -0.006526303477585316, 0.023018701002001762, -0.05030149966478348, 0.015321008861064911, -0.014651644043624401, -0.02620437927544117, -0.010418534278869629, 0.0044872211292386055, -0.04345910623669624, -0.08007582277059555, -0.048367779701948166, -0.004741331562399864, 0.11225490272045135, 0.014577270485460758, 0.012042362242937088, 0.04477304592728615, 0.004586386028677225, -0.1241547092795372, -0.004831199999898672, -0.05171460285782814, -0.0645069032907486, -0.07605963945388794, -0.01336249802261591, 0.024940023198723793, 0.009662399999797344, 0.059598229825496674, -0.04717779904603958, -0.02113456279039383, 0.01899011805653572, -0.13238541781902313, -0.06797768175601959, 0.059895724058151245, -0.001645520911552012, 0.005041925702244043, -0.11641983687877655, -0.010368951596319675, 0.04093039780855179, 0.0046266717836260796, -0.029997443780303, 0.05597870051860809, 0.13278207182884216, -0.11661816388368607, -0.02667541243135929, 0.09455392509698868, 0.037657950073480606, 0.03056764416396618, -0.008769913576543331, -0.050450246781110764, 0.015271426178514957, 0.002513215644285083, -0.09009149670600891, -0.11770898103713989, 0.007102700881659985, -0.02667541243135929, -0.037533991038799286, -0.0039975931867957115, 0.10342920571565628, 0.07209303230047226, 0.09450434893369675, 0.01718035526573658, -0.1742330938577652, 0.025175541639328003, 0.029427245259284973, 0.046681974083185196, 0.027741437777876854, -0.03540194407105446, -0.11403986811637878, -0.011918406002223492, 0.006296984385699034, -0.10382586717605591, -0.05107003077864647, -0.04995442181825638, 0.028584342449903488, 0.1998176872730255, -0.009067409671843052, 0.06534980237483978, 0.0669364482164383, 0.048590902239084244, -0.044054098427295685, -0.1306004375219345, 0.017725761979818344, -0.006321775261312723, 0.09490100294351578, -0.007350613363087177, 0.1059083342552185, -0.06331691890954971, -0.0445995070040226, 0.03396404907107353, -0.07834043353796005, 0.1299062818288803, 0.10481751710176468, -0.09405810385942459, -0.08686862885951996, -0.020018955692648888, -0.015011117793619633, 0.045045748353004456, -0.01735389418900013, -0.13575702905654907, -0.0363440103828907, 0.001086942502297461, 0.022745996713638306, -0.018531478941440582, 0.036071307957172394, 0.008714133873581886, -0.011106492020189762, 0.0525079220533371, -0.004849793389439583, -0.03862480819225311, -0.03993874788284302, -0.0891990140080452, 0.07938166707754135, -0.014775600284337997, 0.10600749403238297, -0.02475409023463726, 0.038228146731853485, 0.07318384945392609, -0.01018921472132206, -0.007951801642775536, 0.0008769914275035262, 0.054193731397390366, 0.03996353596448898, -0.06772976368665695, -0.081563301384449, -0.0414758063852787, 0.078241266310215, -0.07184512168169022, -0.013003024272620678, -0.0407816506922245, 0.03812898322939873, -0.021642783656716347, -0.048690065741539, -0.17681138217449188, -0.049235474318265915, -0.003889131359755993, 0.004580188076943159, -0.03983958065509796, -0.08463741838932037, -0.21340329945087433, -0.06282109767198563, -0.0695643201470375, -0.09063690900802612, -0.022027049213647842, 0.008838090114295483, 0.05374748632311821, 0.09509933739900589, 0.04891318827867508, 0.04747529327869415, 0.04826861619949341, 0.06153194606304169, -0.0306915994733572, 0.08622405678033829, 0.03924459218978882, -0.04393014311790466, -0.02258485183119774, -0.03098909556865692, 0.0021181046031415462, 0.046731557697057724, 0.007220459170639515, 0.007610921747982502, 0.17165479063987732, 0.1135440468788147, 0.03664150461554527, 0.06901891529560089, 0.0898931697010994, -0.023725250735878944, 0.05642494559288025, -0.037583574652671814, -0.002869590185582638, 0.04122789204120636, -0.04762404039502144, 0.02940245345234871, -0.03535236045718193, 0.03379051014780998, 0.06718435883522034, 0.11275072395801544, -0.013907905668020248, 0.08354660123586655, -0.03448466584086418, 0.07139887660741806, 0.005082211457192898, 0.00738160265609622, 0.05201209709048271, 0.03629442676901817, 0.02184111438691616, -0.08265411853790283, 0.08518282324075699, 0.09792554378509521, -0.012686935253441334, -0.057267848402261734, -0.01990739442408085, -0.07293593138456345, -0.07710087299346924, 0.016498593613505363, 0.008831892162561417, 0.04442596808075905, 0.007009733468294144, -0.029551200568675995, -0.017081189900636673, 0.008131538517773151, -0.05766450986266136, -0.011391591280698776, 0.07640671730041504, -0.029328079894185066, -0.03004702739417553, 0.08062122762203217, 0.03056764416396618, 0.004171132110059261, 0.04866527393460274, 0.07898500561714172, -0.036715880036354065, -0.06857267022132874, -0.04122789204120636, -0.015147469937801361, -0.04581427946686745, 0.07551422715187073, 0.03143533691763878, -0.005227860528975725, -0.06019321829080582, 0.019064491614699364], 'score': 4.344019412994385}, page_content='It has been proposed that epithelial-mesenchymal transition (EMT) in mammary epithelial cells and breast cancer cells generates stem cell features, and that the presence of EMT characteristics in claudin-low breast tumors reveals their origin in basal stem cells. It remains to be determined, however, whether EMT is an inherent property of normal basal stem cells, and if the presence of a mesenchymal-like phenotype is required for the maintenance of all their stem cell properties. We used nontumorigenic basal cell lines as models of normal stem cells/progenitors and demonstrate that these cell lines contain an epithelial subpopulation (\"EpCAM+,\" epithelial cell adhesion molecule positive [EpCAM(pos)]/CD49f(high)) that spontaneously generates mesenchymal-like cells (\"Fibros,\" EpCAM(neg)/CD49f(med/low)) through EMT. Importantly, stem cell/progenitor properties such as regenerative potential, high aldehyde dehydrogenase 1 activity, and formation of three-dimensional acini-like structures predominantly reside within EpCAM+ cells, while Fibros exhibit invasive behavior and mammosphere-forming ability. A gene expression profiling meta-analysis established that EpCAM+ cells show a luminal progenitor-like expression pattern, while Fibros most closely resemble stromal fibroblasts but not stem cells. Moreover, Fibros exhibit partial myoepithelial traits and strong similarities with claudin-low breast cancer cells. Finally, we demonstrate that Slug and Zeb1 EMT-inducers control the progenitor and mesenchymal-like phenotype in EpCAM+ cells and Fibros, respectively, by inhibiting luminal differentiation. In conclusion, nontumorigenic basal cell lines have intrinsic capacity for EMT, but a mesenchymal-like phenotype does not correlate with the acquisition of global stem cell/progenitor features. Based on our findings, we propose that EMT in normal basal cells and claudin-low breast cancers reflects aberrant/incomplete myoepithelial differentiation.'),\n", + " Document(metadata={'_id': '10931595', 'title': 'Geometry, epistasis, and developmental patterning.', 'embedding': [0.0491923987865448, 0.05855976790189743, 0.12226885557174683, 0.09674139320850372, 0.0009851831709966063, 0.04300226271152496, 0.13486824929714203, -0.06425688415765762, -0.04122191295027733, 0.09455019980669022, 0.07723972946405411, -0.03651083633303642, 0.0463438406586647, -0.012647321447730064, 0.03412790969014168, -0.07636325061321259, 0.09811089187860489, 0.001799179008230567, -0.010462970472872257, 0.11142241954803467, 0.08271772414445877, -0.0002925163717009127, 0.02873208560049534, 0.05861454829573631, 0.0058135222643613815, -0.007326818536967039, 0.10638266801834106, 0.12303577363491058, 0.055108632892370224, -0.023418430238962173, 0.15305519104003906, -0.03514133766293526, -0.05620422959327698, -0.0005717657622881234, -0.1791304498910904, 0.06568115949630737, 0.04689163714647293, 0.06650286167860031, -0.008614147081971169, 0.09975429624319077, 0.012647321447730064, -0.02708868682384491, -0.14111316204071045, 0.06064140796661377, -0.08907220512628555, -0.015352081507444382, -0.06354474276304245, 0.025773966684937477, 0.0129280686378479, 0.06765323877334595, -0.037825558334589005, -0.0019857732113450766, 0.10643744468688965, 0.05812152847647667, -0.11470922082662582, 0.012010504491627216, -0.02544528804719448, -0.06650286167860031, -0.051986172795295715, -0.023185614496469498, 0.002949557965621352, -0.061189208179712296, 0.0013737784465774894, 0.034894827753305435, 0.040537163615226746, 0.00023281479661818594, -0.0583406500518322, -0.023897754028439522, 0.005751894786953926, 0.03670256957411766, 0.0245961993932724, -0.08759314566850662, 0.06962531805038452, 0.038428135216236115, 0.047603778541088104, -0.007819837890565395, -0.01333891786634922, 0.15930010378360748, -0.005632063839584589, 0.026540886610746384, 0.09641271829605103, -0.022131100296974182, 0.06672198325395584, -0.0807456523180008, -0.07340513914823532, -0.027882995083928108, 0.015653371810913086, -0.07187129557132721, -0.16927005350589752, -0.0331144817173481, 0.02096702717244625, -0.05089057609438896, -0.11186066269874573, 0.07795187085866928, 0.06162744760513306, 0.04974019527435303, 0.010120595805346966, -0.03829118609428406, 0.0797596126794815, -0.04048238322138786, 0.034675709903240204, -0.023829279467463493, 0.005549893714487553, -0.051986172795295715, 0.05916234850883484, -0.013058170676231384, -0.11470922082662582, 0.0668315440416336, 0.014516687020659447, -0.006036065984517336, 0.08666188269853592, 0.011175110004842281, -0.0023914873600006104, 0.04341311380267143, -0.024842707440257072, -0.13103364408016205, -0.1573280245065689, -0.034894827753305435, 0.04853503778576851, 0.07477463781833649, -0.027157161384820938, 0.0228569358587265, 0.009545406326651573, 0.023322565481066704, 0.1053418442606926, 0.0062551856972277164, -0.05773806944489479, -0.017050260677933693, -0.003974970430135727, -0.02387036383152008, -0.00985354371368885, 0.06962531805038452, -0.008874352090060711, -0.034073129296302795, -0.14023667573928833, -0.03788033500313759, -0.003509340574964881, 0.12533652782440186, -0.021240927278995514, 0.032429732382297516, -0.012325488962233067, 0.06595506519079208, 0.03462092950940132, -0.036127377301454544, -0.009107166901230812, 0.07477463781833649, -0.0038209017366170883, 0.07395293563604355, -0.06770802289247513, 0.11361362040042877, -0.02232282981276512, 0.026472412049770355, 0.04437176138162613, -0.0665576383471489, -0.012037894688546658, -0.08710012584924698, -0.07384337484836578, 0.0362643264234066, -0.05642335116863251, 0.015721846371889114, -0.05850498750805855, 0.04771333932876587, 0.029964633285999298, 0.09098950028419495, -0.06294216215610504, 0.11722909659147263, -0.09953517466783524, -0.0014987452886998653, -0.08080042898654938, 0.031087622046470642, 0.027294110506772995, -0.0012684982502833009, -0.07619891315698624, -0.0728573352098465, -0.042618803679943085, -0.06502380222082138, -0.09816567599773407, -0.11755777895450592, -0.08425156772136688, -0.12270709127187729, -0.001509016496129334, 0.05590293928980827, -0.06710544228553772, -0.01939210295677185, 0.04204361140727997, 0.04598776996135712, 0.03966068476438522, 0.07022789865732193, -0.011928334832191467, -0.04108496382832527, -0.013332070782780647, 0.038674645125865936, 0.13946975767612457, 0.02604786679148674, 0.04371440038084984, -0.031553253531455994, 0.11071028560400009, 0.006289423443377018, 0.08836006373167038, -0.10709480941295624, 0.050123654305934906, 0.011209347285330296, 0.07828055322170258, -0.06896796077489853, -0.0463438406586647, 0.011209347285330296, -0.06989921629428864, -0.05163010582327843, -0.033634889870882034, 0.06140832602977753, 0.03924983739852905, -0.0782257691025734, -0.02834862470626831, 0.03938678652048111, -0.037414707243442535, -0.0020679431036114693, -0.0800882875919342, -0.0012308370787650347, 0.0334157720208168, 0.012188538908958435, -0.04127669334411621, 0.019337322562932968, 0.021391570568084717, 0.033881399780511856, -0.06343518197536469, -0.004341311287134886, 0.03683951869606972, -0.0435226708650589, -0.03308708965778351, 0.010106900706887245, 0.03560696914792061, 0.07723972946405411, 0.011757147498428822, 0.0030128974467515945, -0.06124398484826088, 0.04018109664320946, -0.03670256957411766, 0.026294376701116562, 0.01105185505002737, -0.05168488621711731, -0.03725036606192589, 0.05538253113627434, -0.04938412830233574, 0.06518813967704773, -0.03081372380256653, 0.08463502675294876, -0.029307274147868156, -0.057409390807151794, -0.15710890293121338, -0.07351469248533249, -0.005056874360889196, 0.05631379038095474, 0.06376386433839798, 0.022473474964499474, -0.029690733179450035, -0.011031312867999077], 'score': 4.270141124725342}, page_content='Developmental signaling networks are composed of dozens of components whose interactions are very difficult to quantify in an embryo. Geometric reasoning enumerates a discrete hierarchy of phenotypic models with a few composite variables whose parameters may be defined by in vivo data. Vulval development in the nematode Caenorhabditis elegans is a classic model for the integration of two signaling pathways; induction by EGF and lateral signaling through Notch. Existing data for the relative probabilities of the three possible terminal cell types in diverse genetic backgrounds as well as timed ablation of the inductive signal favor one geometric model and suffice to fit most of its parameters. The model is fully dynamic and encompasses both signaling and commitment. It then predicts the correlated cell fate probabilities for a cross between any two backgrounds/conditions. The two signaling pathways are combined additively, without interactions, and epistasis only arises from the nonlinear dynamical flow in the landscape defined by the geometric model. In this way, the model quantitatively fits genetic experiments purporting to show mutual pathway repression. The model quantifies the contributions of extrinsic vs. intrinsic sources of noise in the penetrance of mutant phenotypes in signaling hypomorphs and explains available experiments with no additional parameters. Data for anchor cell ablation fix the parameters needed to define Notch autocrine signaling.'),\n", + " Document(metadata={'_id': '27049238', 'title': 'Large deformation of red blood cell ghosts in a simple shear flow.', 'embedding': [0.05452635511755943, 0.04289012402296066, 0.15307152271270752, 0.14737433195114136, -0.0037488548550754786, -0.009466194547712803, -0.005717339459806681, -0.004434129223227501, -0.02102852240204811, -0.01877114735543728, 0.011300311423838139, -0.0030518232379108667, -0.1063116118311882, 0.060572896152734756, 0.0384022481739521, 0.10840774327516556, 0.05863800272345543, -0.028002198785543442, -0.04452940821647644, 0.03399499133229256, 0.06422769278287888, 0.004235937260091305, 0.025005802512168884, 0.11018139868974686, -0.010796433314681053, -0.013356135226786137, 0.10389299690723419, 0.037703536450862885, 0.01842179149389267, -0.10480669140815735, 0.05933671444654465, -0.05011909827589989, 0.05084468424320221, -0.06304525583982468, -0.058799244463443756, 0.13544249534606934, -0.016030048951506615, 0.1063116118311882, -0.055789411067962646, -0.0007440603221766651, 0.06530263274908066, 0.020356684923171997, -0.011804189532995224, 0.12146827578544617, 0.012166982516646385, 0.03160325065255165, -0.012200574390590191, -0.05350515991449356, 0.03665547072887421, 0.09636840969324112, -0.036951079964637756, 0.036279238760471344, 0.03848286718130112, -0.00543516781181097, -0.10975141823291779, -0.0017434190958738327, -0.01842179149389267, 0.046141818165779114, -0.03945031389594078, -0.05557442083954811, -0.03595675900578499, -0.013154583983123302, -0.10545165836811066, -0.02308434620499611, -0.027088498696684837, 0.006389177404344082, -0.18574970960617065, -0.01831429824233055, 0.015371648594737053, 0.07959934324026108, -0.023662127554416656, -0.04057900235056877, -0.015317901968955994, -0.036870457231998444, -0.09077872335910797, -0.060626640915870667, 0.024495204910635948, 0.03649422898888588, 0.014310144819319248, 0.08723141998052597, 0.04834544658660889, -0.09228363633155823, 0.038348499685525894, -0.014242961071431637, -0.049044158309698105, -0.022036278620362282, 0.10760153830051422, -0.02581200748682022, -0.07191351801156998, -0.018878642469644547, -0.027478165924549103, 0.049527883529663086, -0.07169853150844574, -0.0010589843150228262, -0.07922311127185822, 0.058208025991916656, -0.04735112562775612, -0.06637757271528244, 0.041895803064107895, 0.017803700640797615, 0.04111647233366966, 0.03678983822464943, -0.0250998605042696, 0.03455933555960655, 0.058208025991916656, -0.040122151374816895, -0.03359188884496689, -0.01877114735543728, 0.009728210978209972, -0.002736059483140707, 0.1754302829504013, -0.07368716597557068, 0.02645697258412838, -0.0478348508477211, 0.09072497487068176, -0.06997862458229065, -0.07761070132255554, -0.0009069810039363801, -0.10894521325826645, 0.03058205544948578, -0.012059488333761692, 0.008324069902300835, 0.08099676668643951, -0.017199046909809113, 0.08056678622961044, -0.05992792919278145, 0.054902583360672, -0.07809442281723022, -0.08793012797832489, -0.04834544658660889, 0.0041485982947051525, -0.008995908312499523, 0.018059000372886658, -0.13318511843681335, -0.0933048352599144, 0.0006290081073530018, 0.02875465713441372, 0.07411714643239975, 0.09255237132310867, -0.03872473165392876, 0.0069803944788873196, 0.06573260575532913, 0.10706406831741333, 7.762875611661002e-05, -0.01225432101637125, 0.0762132778763771, -0.014068283140659332, 0.07814817130565643, 0.021458499133586884, 0.043427594006061554, -0.011051731184124947, 0.08637146651744843, 0.020826971158385277, 0.011851218529045582, 0.019348928704857826, -0.064980149269104, 0.11050388216972351, -0.0034095768351107836, -0.004773407708853483, 0.04498625919222832, -0.0703011080622673, -0.02179441787302494, -0.07363342493772507, -0.10727905482053757, -0.11050388216972351, 0.020679166540503502, -0.032167594879865646, -0.03335002809762955, -0.04627618566155434, 0.019335491582751274, 0.04286324977874756, -0.03171074390411377, -0.08723141998052597, -0.08991876989603043, -0.020504489541053772, 0.050468456000089645, 0.0206657312810421, -0.09712087363004684, 0.01800525188446045, 0.08465155959129333, 0.038885969668626785, 0.032167594879865646, -0.0286471638828516, 0.006795639172196388, -0.03348439559340477, 0.07212850451469421, 0.08948879688978195, 0.08260917663574219, -0.001447810442186892, -0.027625970542430878, -0.08492029458284378, 0.060196664184331894, 0.03372625634074211, -0.08400660008192062, -0.11233127862215042, -0.07056984305381775, 0.06815122812986374, 0.0011312068672850728, -0.02604043297469616, -0.04740487411618233, 0.1174909919500351, -0.004995114170014858, 0.05345141515135765, -0.14318206906318665, -0.05275270342826843, 0.001909698941744864, -0.06401270627975464, 0.038348499685525894, 0.0277603380382061, 0.04976974427700043, 0.09975447505712509, 0.03052830882370472, -0.03087766468524933, 0.02402491867542267, -0.0419495515525341, -0.09932450205087662, 0.02551640011370182, 0.06691504269838333, -0.001196711091324687, 0.019120503216981888, -0.07218225300312042, 0.0602504126727581, 0.18295486271381378, 0.14952421188354492, -0.1494167298078537, -0.014175777323544025, 0.12480058521032333, 0.008848103694617748, -0.10222683846950531, 0.022708117961883545, 0.043669454753398895, -0.0037454955745488405, 0.0010312709491699934, 0.008230012841522694, -0.0014637665590271354, -0.013530813157558441, -0.06637757271528244, 0.05568191409111023, -0.0011228088987991214, -0.08744640648365021, -0.055843155831098557, 0.07309595495462418, -0.022170646116137505, -0.11082635819911957, -0.02491174452006817, 0.02958773635327816, -0.05232272669672966, -0.05089842900633812, 0.09088621288537979, -0.014189214445650578, -0.04702864587306976, -0.010762841440737247, 0.06858120113611221, -0.05393513664603233, -0.03920845314860344, 0.0036010504700243473], 'score': 4.082460880279541}, page_content='Red blood cells are known to change shape in response to local flow conditions. Deformability affects red blood cell physiological function and the hydrodynamic properties of blood. The immersed boundary method is used to simulate three-dimensional membrane-fluid flow interactions for cells with the same internal and external fluid viscosities. The method has been validated for small deformations of an initially spherical capsule in simple shear flow for both neo-Hookean and the Evans-Skalak membrane models. Initially oblate spheroidal capsules are simulated and it is shown that the red blood cell membrane exhibits asymptotic behavior as the ratio of the dilation modulus to the extensional modulus is increased and a good approximation of local area conservation is obtained. Tank treading behavior is observed and its period calculated.'),\n", + " Document(metadata={'_id': '95764370', 'title': 'Modification in the chemical bath deposition apparatus, growth and characterization of CdS semiconducting thin films for photovoltaic applications', 'embedding': [0.035667359828948975, -0.017749670892953873, 0.037035487592220306, 0.08981645852327347, 0.006480610463768244, 0.05136483907699585, -0.012877212837338448, -0.1198192834854126, 0.05976562947034836, -0.10004141926765442, 0.055493228137493134, -0.04894061014056206, -0.09236069768667221, -0.03890766575932503, 0.12874813377857208, 0.08501600474119186, -0.03938771039247513, 0.03249906003475189, 0.013453267514705658, -0.013885308057069778, 0.05899755656719208, 0.03876364976167679, -0.026618506759405136, 0.011263060383498669, -0.04015578329563141, -0.09048852324485779, 0.1407492607831955, 0.020845962688326836, 0.07762330770492554, -0.05885354429483414, -0.0011761108180508018, -0.06259789317846298, -0.046972423791885376, -0.03998776525259018, -0.15092621743679047, 0.11597892642021179, 0.034491248428821564, 0.020773956552147865, -0.0627899169921875, -0.03300310671329498, 0.036315418779850006, 0.00783073715865612, -0.025010354816913605, 0.011695101857185364, -0.06576619297266006, 0.010338974185287952, -0.09341679513454437, 0.10052146762609482, 0.04853257164359093, 0.012721198610961437, -0.08568806946277618, 0.06043769419193268, 0.07603916525840759, -0.05126882717013359, 0.028034640476107597, -0.03269108012318611, -0.055925268679857254, 0.022946162149310112, -0.013741293922066689, -0.046804409474134445, 0.05011672154068947, -0.07757530361413956, -0.024674324318766594, -0.0016486552776768804, -0.04930064454674721, -0.03185100108385086, -0.013345257379114628, 0.05405309051275253, 0.08151167631149292, -0.026642508804798126, 0.06019767001271248, 0.04229198396205902, 0.0038643640000373125, 0.07301487773656845, -0.057173386216163635, 0.0043534100987017155, 0.0037863566540181637, -0.035643357783555984, -0.017089609056711197, 0.08957643806934357, -0.004590432159602642, -0.047308456152677536, -0.05112481489777565, -0.025826431810855865, -0.03974774479866028, -0.07018261402845383, 0.12711597979068756, 0.0018616752931848168, -0.11530686169862747, -0.001717661740258336, 0.011089044623076916, 0.03218703344464302, -0.08386389911174774, 0.036867473274469376, -0.04915662854909897, -0.04322807118296623, -0.03317112475633621, -0.028538687154650688, -0.006684629712253809, 0.09116058796644211, 0.055493228137493134, 0.03398720175027847, 0.005010472144931555, -0.02909073978662491, 0.045844316482543945, 0.011473081074655056, -0.044980235397815704, -0.013009225018322468, 0.011839115060865879, -0.05477315932512283, 0.17281627655029297, -0.01688558980822563, 0.08031156659126282, 0.06307794153690338, 0.014221339486539364, -0.019429830834269524, -0.03115493431687355, 0.014713386073708534, -0.0750790685415268, 0.12769202888011932, -0.09346480667591095, 0.11722704023122787, 0.06725433468818665, -0.024362294003367424, 0.0789194330573082, -0.008004753850400448, -0.015229434706270695, -0.13921311497688293, -0.044140156358480453, 0.03468326851725578, 0.020821960642933846, -0.011209055781364441, 0.05203690007328987, -0.18174511194229126, -0.05952560529112816, -0.12231551855802536, 0.035835374146699905, 0.006348597817122936, 0.035355329513549805, -0.0046984427608549595, 0.11261861026287079, 0.06211785227060318, 0.11261861026287079, 0.09740117192268372, -0.054581139236688614, -0.07099868357181549, 0.044812221080064774, -0.011785110458731651, -0.044860225170850754, 0.06576619297266006, -0.0603896863758564, 0.04934864863753319, 0.09917733818292618, -0.05045275017619133, 0.011557088233530521, -0.01455737091600895, -0.019285816699266434, 0.07594314962625504, -0.035787370055913925, 0.09610505402088165, 0.05328501760959625, 0.02133801020681858, 0.0016801581950858235, -0.0654301643371582, -0.03285909444093704, -0.036939479410648346, 0.001304372912272811, 0.035763368010520935, -0.06307794153690338, 0.028850717470049858, 0.05347703769803047, -0.08856834471225739, 0.03348315507173538, -0.001587149454280734, -0.05155685544013977, -0.022502118721604347, 0.012961220927536488, -0.06499812006950378, -0.08794428408145905, 0.012553182430565357, 0.04831654950976372, -0.011695101857185364, -0.06912650913000107, -0.10426582396030426, 0.009624906815588474, -0.12202749401330948, -0.03782756254076958, 0.036651451140642166, 0.007554711773991585, -0.055877264589071274, -0.03281109035015106, -0.05078878253698349, 0.057317398488521576, -0.015625471249222755, -0.056597329676151276, -0.008736822754144669, 0.09370482712984085, 0.11722704023122787, -0.002305717207491398, -0.07047063857316971, -0.014761390164494514, 0.004653438460081816, -0.03062688559293747, 0.11002635955810547, -0.07992752641439438, -0.046300359070301056, -0.12154744565486908, -0.03089090995490551, 0.06840644031763077, -0.06034168228507042, 0.03276308625936508, 0.09634507447481155, -0.058037467300891876, -0.004578431136906147, -0.03785156458616257, 0.024554312229156494, -0.004920463543385267, -0.03348315507173538, 0.04238799214363098, 0.007710726466029882, -0.05184488371014595, 0.021686041727662086, 0.036915477365255356, -0.00846679788082838, -0.005127483047544956, 0.07618317753076553, -0.1164589673280716, 0.027002543210983276, 0.05434111878275871, -0.1445896178483963, -0.00472244480624795, 0.022658133879303932, -0.08410391956567764, 0.0998494029045105, -0.02213008515536785, -0.009354881010949612, 0.026162464171648026, 0.09135260432958603, -0.10935430228710175, -0.05338102951645851, -0.0844399556517601, -0.017989695072174072, -0.008070760406553745, 0.07647120207548141, -0.0377795584499836, 0.08520802855491638, -0.03885966166853905, -0.10340174287557602, 0.00032440555514767766, 0.05904556065797806, -0.13066831231117249, -0.03386719152331352, -0.09226468950510025, -0.11473080515861511, -0.09111258387565613, -0.09567300975322723], 'score': 3.966486930847168}, page_content='Abstract In this paper, growth and characterization of CdS thin films by Chemical Bath Deposition (CBD) technique using the reaction between CdCl 2 , (NH 2 ) 2 CS and NH 3 in an aqueous solution has been reported. The parameters actively involved in the process of deposition have been identified. A commonly available CBD system has been sucessfully modified to obtain the precious control over the pH of the solution at 90°C during the deposition and studies have been made to understand the fundamental parameters like concentrations of the solution, pH and temperature of the solution involved in the chemical bath deposition of CdS. It is confirmed that the pH of the solution plays a vital role in the quality of the CBD–CdS films. Structural, optical and electrical properties have been analysed for the as-deposited and annealed films. XRD studies on the CBD–CdS films reveal that the change in Cadmium ion concentration in the bath results in the change in crystallization from cubic phase with (1 1 1) predominant orientation to a hexagonal phase with (0 0 2) predominant orientation. The structural changes due to varying cadmium ion concentration in the bath affects the optical and electrical properties. Optimum electrical resistivity, band gap and refractive index value are observed for the annealed films deposited from 0.8 M cadmium ion concentration. The films are suitable for solar cell fabrication. Further on, annealing the samples at 350°C in H 2 for 30 min resulted in an increased diffraction intensity as well as shifts in the peak towards lower scattering angles due to enlarged CdS unit cell. This in turn brought about an increase in the lattice parameters and narrowing in the band-gap values. The results are compared with the analysis of previous work.'),\n", + " Document(metadata={'_id': '803312', 'title': 'Cerebral organoids model human brain development and microcephaly', 'embedding': [0.011010420508682728, -0.014564870856702328, 0.06692420691251755, 0.1460077464580536, -0.06117963790893555, -0.10455112159252167, 0.038536470383405685, 0.06668484956026077, -0.01862197183072567, -0.029010063037276268, 0.03166692703962326, -0.06826460361480713, 0.023253528401255608, -0.11192331463098526, -0.0015618042089045048, -0.07362619787454605, 0.012626079842448235, -0.07668997347354889, 0.06558381021022797, 0.08851420134305954, 0.08253028243780136, 0.01463667768985033, 0.01928020268678665, 0.020201727747917175, 0.06701994687318802, 0.010441947728395462, 0.026065973564982414, -0.004093003924936056, 0.009861506521701813, 0.037196069955825806, 0.030948854982852936, -0.03463495150208473, 0.005340652074664831, 0.030350463464856148, -0.10435963422060013, 0.014421257190406322, 0.0683603510260582, 0.051701102405786514, -0.08339196443557739, 0.1357632726430893, 0.09033332020044327, -0.06338172405958176, 0.12322096526622772, 0.11010420322418213, -0.05198833346366882, 0.042078953236341476, -0.10388091951608658, -0.021362608298659325, -0.0616583526134491, 0.12389115989208221, -0.03657374531030655, 0.030733434483408928, 0.06007859855890274, 0.022894492372870445, -0.0929662436246872, 0.04483155906200409, -0.01707811839878559, -0.016754986718297005, -0.07262089848518372, -0.011471182107925415, 0.03391687944531441, -0.0036382258404046297, 0.10589151829481125, 0.056392498314380646, 0.004006237257272005, -0.02640107274055481, -0.09066841751337051, -0.10426389425992966, 0.10052992403507233, 0.04195927456021309, -0.056871213018894196, -0.049786247313022614, -0.02697552926838398, -0.04796713590621948, 0.05270640179514885, -0.04653099179267883, 0.028100507333874702, 0.05442977324128151, 0.09095564484596252, 0.11747639626264572, 0.044687945395708084, -0.03592747822403908, 0.10455112159252167, -0.05969562754034996, -0.015809526666998863, -0.0036591694224625826, 0.03587960824370384, 0.031427569687366486, -0.07769527286291122, -0.021147187799215317, -0.027095207944512367, -0.056966956704854965, -0.03410836681723595, 0.09713105112314224, 0.027286693453788757, -0.056871213018894196, -0.005119246896356344, -0.09909377992153168, 0.1312633603811264, 0.10780637711286545, -0.024534087628126144, -0.012865436263382435, -0.03942209109663963, 0.031714797019958496, 0.005241917446255684, 0.07549318671226501, -0.0073003871366381645, -0.013080857694149017, -0.035759929567575455, 0.06323810666799545, 0.1440928876399994, -0.020177790895104408, 0.02295433171093464, 0.0033420214895159006, 0.04645918682217598, -0.011309616267681122, -0.09210456162691116, -0.028531350195407867, -0.0010688784532248974, 0.028052635490894318, 0.017736351117491722, 0.06117963790893555, 0.08099839836359024, -0.04748842120170593, 0.04873307794332504, -0.07429639995098114, 0.07003584504127502, 0.040164098143577576, 0.03312700241804123, -0.05825948342680931, -0.002552143530920148, 0.056966956704854965, -0.04174385219812393, -0.07544531673192978, -0.12465710192918777, 0.043539032340049744, -0.09861506521701813, 0.07147198915481567, -0.017508961260318756, -0.0969395712018013, -0.00879038404673338, 0.00045216025318950415, 0.08798761665821075, -0.05280214548110962, 0.01658743806183338, 0.03504185751080513, 0.020225662738084793, 0.11240202933549881, -0.14131635427474976, 0.13921000063419342, 0.005241917446255684, 0.018071450293064117, 0.04997773468494415, -0.04502304270863533, -0.055530816316604614, 0.07132837176322937, 0.07003584504127502, 0.06678058952093124, -0.07305174320936203, -0.09928526729345322, 0.018574099987745285, 0.03516153618693352, -0.01959136687219143, 0.0037938079331070185, -0.08578553795814514, 0.0980406105518341, -0.07372194528579712, 0.009939298033714294, -0.08779612928628922, -0.043156061321496964, -0.04835010692477226, -0.016180530190467834, -0.13040167093276978, 0.008951949886977673, -0.07017946243286133, 0.03765084967017174, -0.04959476366639137, 0.019603334367275238, -0.0023397142067551613, -0.056488242000341415, 0.052084073424339294, 0.08339196443557739, -0.06496147811412811, 0.10876379907131195, 0.04277309030294418, 0.015630008652806282, -0.10416814684867859, -0.054669130593538284, 0.008700625039637089, -0.013356118462979794, -0.016443822532892227, -0.14074189960956573, 0.058403097093105316, 0.053711701184511185, 0.07089753448963165, -0.03252860903739929, 0.10512557625770569, 0.034299854189157486, 0.023959631100296974, -0.06826460361480713, 0.04107365384697914, 0.028818577527999878, -0.025371838361024857, -0.0894237607717514, 0.09267901629209518, 0.06132325157523155, 0.03324668109416962, 0.057828642427921295, 0.02879464253783226, 0.10388091951608658, 0.07597190141677856, -0.01650366187095642, 0.01774831861257553, 0.08401429653167725, -0.030015362426638603, -0.11948699504137039, -0.06156260892748833, -0.026736171916127205, -0.006731914356350899, -0.0014174419920891523, -0.007072998210787773, 0.01382286474108696, 0.04437677934765816, 0.06400404870510101, 0.014612742699682713, -0.03310306742787361, -0.028435606509447098, -0.032600417733192444, -0.01862197183072567, -0.016264304518699646, 0.12733790278434753, 0.024725573137402534, 0.0036681455094367266, -0.007527776528149843, 0.07448788732290268, 0.0374593660235405, 0.0012887875782325864, -0.058690328150987625, -0.010232510045170784, -0.1169019415974617, 0.04014016315340996, 0.06634975224733353, -0.056105270981788635, 0.006725930608808994, 0.108285091817379, 0.05749354138970375, 0.0081022335216403, -0.12762513756752014, -0.046602800488471985, -0.061466868966817856, -0.007444001268595457, -0.04502304270863533, 0.07238154113292694, -0.042557667940855026, -0.08008883893489838, 0.030565883964300156], 'score': 3.780266761779785}, page_content='The complexity of the human brain has made it difficult to study many brain disorders in model organisms, highlighting the need for an in vitro model of human brain development. Here we have developed a human pluripotent stem cell-derived three-dimensional organoid culture system, termed cerebral organoids, that develop various discrete, although interdependent, brain regions. These include a cerebral cortex containing progenitor populations that organize and produce mature cortical neuron subtypes. Furthermore, cerebral organoids are shown to recapitulate features of human cortical development, namely characteristic progenitor zone organization with abundant outer radial glial stem cells. Finally, we use RNA interference and patient-specific induced pluripotent stem cells to model microcephaly, a disorder that has been difficult to recapitulate in mice. We demonstrate premature neuronal differentiation in patient organoids, a defect that could help to explain the disease phenotype. Together, these data show that three-dimensional organoids can recapitulate development and disease even in this most complex human tissue.'),\n", + " Document(metadata={'_id': '10906636', 'title': 'The carboxyl terminus of human cytomegalovirus-encoded 7 transmembrane receptor US28 camouflages agonism by mediating constitutive endocytosis.', 'embedding': [-0.031789202243089676, 0.04996145889163017, 0.0008426404092460871, 0.10550684481859207, -0.11373579502105713, 0.0509410984814167, 0.07332579046487808, -0.058974117040634155, 0.03852420300245285, -0.08126084506511688, 0.05481066182255745, -0.0001735410769470036, 0.027699220925569534, 0.04616536945104599, 0.05564335361123085, -0.12000546604394913, -0.053439170122146606, 0.023229630663990974, -0.02718491293489933, 0.08326909691095352, 0.0722481906414032, 0.05123498663306236, -0.03338111191987991, 0.10511499643325806, -0.08390586078166962, -0.009686155244708061, 0.014204729348421097, 0.016482383012771606, -0.055447425693273544, 0.027821676805615425, 0.04626333341002464, -0.05236157029867172, 0.0005981139838695526, -0.09595539420843124, -0.13264277577400208, 0.07131753861904144, 0.03583020344376564, 0.03431176766753197, 0.0005747710820287466, 0.05392898619174957, 0.0661744475364685, -0.043275441974401474, 0.020180512219667435, -0.0013913899892941117, -0.08160372078418732, -0.05152887850999832, -0.15008030831813812, 0.01611502096056938, 0.03443422168493271, 0.03073609434068203, 0.028923766687512398, -0.01082498300820589, 0.03734863921999931, 0.084346704185009, -0.12098510563373566, -0.008296296000480652, 0.039871204644441605, 0.044671423733234406, -0.02551952935755253, -0.04449998587369919, 0.028825802728533745, -0.07856684178113937, -0.025299111381173134, -0.06029662489891052, -0.04915326088666916, -0.06073746085166931, -0.10119644552469254, -0.015208856202661991, 0.0386221669614315, -0.015429274179041386, 0.0014679239830002189, -0.045822497457265854, -0.05314527824521065, 0.04606740549206734, 0.034483205527067184, -0.0457245334982872, 0.02877682074904442, 0.035609785467386246, -0.059268005192279816, -0.08488550037145615, 0.0208785030990839, -0.0004622659762389958, 0.042001914232969284, -0.029927894473075867, 0.028972748667001724, -0.001702118432149291, 0.0653417557477951, -0.0745503380894661, -0.022543884813785553, 0.07082771509885788, -0.02461336739361286, 0.09972698986530304, -0.13264277577400208, 0.09193888306617737, -0.048100151121616364, 0.042981550097465515, -0.052753422409296036, -0.0849834606051445, 0.050353314727544785, 0.017633456736803055, -0.056427061557769775, -0.024735821411013603, -0.007488096132874489, -0.0031746344175189734, -0.009086128324270248, 0.04307951405644417, -0.0920858308672905, 0.045234713703393936, 0.0620109885931015, -0.03771600499749184, 0.3113284707069397, -0.019641710445284843, -0.0595129169523716, 0.10344961285591125, -0.01634768396615982, -0.08993063122034073, -0.10766205191612244, 0.04817362502217293, 0.013127128593623638, 0.02618078514933586, -0.03609960526227951, 0.06294164061546326, 0.04533267766237259, 0.020474402233958244, -0.04378975182771683, 0.032352495938539505, 0.08738357573747635, -0.0004974716575816274, -0.08243641257286072, -0.04498980566859245, 0.126960888504982, -0.0563780777156353, -0.0668112114071846, 0.0171191468834877, -0.07440339028835297, 0.008804482407867908, 0.021637720987200737, -0.06588055193424225, -0.08468957245349884, 0.0628436803817749, -0.011265819892287254, 0.029682984575629234, -0.013714910484850407, 0.0008931529591791332, -0.09091026335954666, -0.014951701276004314, -0.12206270545721054, 0.18740445375442505, 0.04621434956789017, 0.049643076956272125, 0.0793505534529686, 0.03134836629033089, 0.1208871379494667, -0.04246724024415016, -0.020180512219667435, -0.06191302463412285, -0.006563564296811819, 0.0340423658490181, -0.05059822276234627, 0.04942265897989273, 0.04690009728074074, 0.050353314727544785, -0.050206370651721954, 0.044402021914720535, 0.028384966775774956, -0.009918819181621075, -0.05525149777531624, -0.014376165345311165, -0.15634998679161072, -0.042418260127305984, -0.008694273419678211, -0.06568462401628494, -0.1380307823419571, -0.05187175050377846, -0.10589870065450668, 0.07352171838283539, 0.015943583101034164, -0.008994287811219692, -0.028409458696842194, 0.033772967755794525, 0.02288675680756569, 0.05907208099961281, 0.07190531492233276, -0.028703348711133003, 0.05099007859826088, -0.021429548040032387, -0.052165642380714417, 0.09620030224323273, -0.06700713187456131, 0.021454038098454475, -0.022372448816895485, -0.04244275018572807, 0.14625972509384155, 0.043422386050224304, -0.03147082030773163, 0.005388000514358282, 0.04065491259098053, 0.017804892733693123, 0.00404100026935339, -0.12020139396190643, -0.054026950150728226, 0.054712697863578796, -0.022972475737333298, -0.10638852417469025, -0.09815957397222519, 0.018221238628029823, -0.01942129246890545, 0.047928713262081146, -0.01388634741306305, -0.0417570061981678, 0.06989706307649612, 0.023388821631669998, 0.028384966775774956, 0.06783982366323471, -0.009061637334525585, -0.035879187285900116, -0.07572589814662933, 0.007910564541816711, -0.0021659149788320065, 0.013690419495105743, 0.047659315168857574, 0.048638951033353806, 0.0388425849378109, 0.017302829772233963, -0.09629826247692108, 0.012894464656710625, -0.07807702571153641, -0.11540117859840393, -0.084346704185009, 0.0014663933543488383, 0.027723712846636772, 0.04376525804400444, 0.015980320051312447, -0.09512270241975784, -0.046973567456007004, 0.044842857867479324, -0.003067486686632037, -0.00983310118317604, 0.07322783023118973, -0.04165904223918915, -0.04219784215092659, 0.022347956895828247, 0.04577351361513138, 0.1474352926015854, -0.046826623380184174, 0.006716632749885321, -0.032376985996961594, -0.0657825917005539, -0.06044356897473335, 0.002020500134676695, 0.03472811356186867, -0.01691097393631935, -0.014437392354011536, -0.0075187101028859615, -0.05270444229245186, 0.06676222383975983], 'score': 3.7103075981140137}, page_content='US28 is one of four 7 transmembrane (7TM) chemokine receptors encoded by human cytomegalovirus and has been shown to both signal and endocytose in a ligand-independent, constitutively active manner. Here we show that the constitutive activity and constitutive endocytosis properties of US28 are separable entities in this viral chemokine receptor. We generated chimeric and mutant US28 proteins that were altered in either their constitutive endocytic (US28 Delta 300, US28 Delta 317, US28-NK1-ctail, and US28-ORF74-ctail) or signaling properties (US28R129A). By using this series of mutants, we show that the cytoplasmic tail domain of US28 per se regulates receptor endocytosis, independent of the signaling ability of the core domain of US28. The constitutive endocytic property of the US28 c-tail was transposable to other 7TM receptors, the herpes virus 8-encoded ORF74 and the tachykinin NK1 receptor (ORF74-US28-ctail and NK1-US28-ctail). Deletion of the US28 C terminus resulted in reduced constitutive endocytosis and consequently enhanced signaling capacity of all receptors tested as assessed by inositol phosphate turnover, NF-kappa B, and cAMP-responsive element-binding protein transcription assays. We further show that the constitutive endocytic property of US28 affects the action of its chemokine ligand fractalkine/CX3CL1 and show that in the absence of the US28 C terminus, fractalkine/CX3CL1 acts as an agonist on US28. This demonstrates for the first time that the endocytic properties of a 7TM receptor can camouflage the agonist properties of a ligand.'),\n", + " Document(metadata={'_id': '13231899', 'title': 'In situ regulation of DC subsets and T cells mediates tumor regression in mice.', 'embedding': [0.07147765904664993, 0.059025105088949203, 0.09424092620611191, 0.1306023895740509, -0.033123794943094254, 0.049835119396448135, 0.099271759390831, 0.07611000537872314, -0.05334674194455147, 0.07929786294698715, 0.006786641664803028, 0.033049076795578, -0.025851501151919365, 0.016860757023096085, 0.03235173597931862, -0.04368355870246887, 0.11536046117544174, 0.02443191036581993, 0.06749284267425537, 0.08652034401893616, 0.05439275503158569, 0.05018379166722298, 0.003947459626942873, -0.04418165981769562, -0.04639821499586105, -0.031106479465961456, -0.007583605125546455, 0.05718212574720383, 0.06749284267425537, 0.05025850608944893, 0.055289339274168015, -0.053645603358745575, -0.0743168443441391, -0.024506626650691032, -0.11575894057750702, 0.03671012818813324, 0.03090723790228367, 0.023734567686915398, 0.008112838491797447, 0.011605780571699142, 0.01672377996146679, -0.023099487647414207, -0.08074235916137695, 0.12691642343997955, -0.058477193117141724, -0.0939420685172081, -0.05553838983178139, -0.10639461874961853, 0.022302523255348206, -0.02353532612323761, 0.043185457587242126, 0.03705880045890808, -0.044480521231889725, 0.14086328446865082, -0.13149896264076233, 0.12054072320461273, 0.001376007217913866, 0.031006859615445137, 0.007932276464998722, -0.006936072371900082, 0.003583222394809127, -0.034941866993904114, 0.06774189323186874, -0.044928815215826035, -0.06644682586193085, -0.03877725079655647, -0.09075421094894409, -0.10450182855129242, 0.03641126677393913, -0.07267310470342636, 0.0033186054788529873, -0.039026305079460144, -0.00028660331736318767, 0.016512086614966393, 0.04612426087260246, 0.02388399839401245, 0.03778104856610298, 0.014519677497446537, -0.01290084607899189, -0.06779170036315918, 0.06515175849199295, 0.01854185201227665, 0.06679549813270569, -0.06271106004714966, -0.0575806088745594, -0.022402144968509674, 0.02209082990884781, 0.00845528393983841, -0.15341545641422272, -0.01754564791917801, 0.044281281530857086, 0.06943544000387192, -0.057829659432172775, 0.0937926322221756, -0.03561430424451828, -0.019774654880166054, -0.008498867973685265, -0.10041739046573639, 0.024830391630530357, 0.045103151351213455, 0.08059293031692505, -0.053745221346616745, 0.008218685165047646, -0.07526323199272156, 0.05030831694602966, -0.043185457587242126, -0.051105279475450516, 0.04089418798685074, 0.04981021583080292, 0.03541506454348564, 0.27873796224594116, 0.05160338431596756, 0.01148748118430376, 0.03359698876738548, -0.07456589490175247, -0.08507584780454636, -0.11546007543802261, 0.008785276673734188, 0.020471997559070587, 0.0412677638232708, -0.00971299223601818, 0.03845348581671715, 0.0015931485686451197, -0.029512552544474602, 0.020322568714618683, -0.04717027395963669, 0.09503789246082306, -0.04186548665165901, -0.11416501551866531, -0.03424452245235443, 0.09319490939378738, -0.045202769339084625, 0.07421722263097763, -0.035564493387937546, -0.12083958089351654, -0.08532489836215973, 0.03937497362494469, -0.0012374725192785263, -0.00782020390033722, 0.01790677197277546, 0.03887687250971794, -0.010472597554326057, 0.0038135945796966553, -0.006030149292200804, -0.08871199190616608, -0.13558340072631836, 0.04844043403863907, 0.017944129183888435, 0.030683092772960663, 0.05235053598880768, -0.00859226193279028, 0.11426463723182678, 0.15660332143306732, 0.09663181751966476, -0.02125651016831398, -0.07351987808942795, 0.02018558979034424, 0.12920770049095154, -0.0047973464243113995, -0.08213704824447632, -0.08313325047492981, 0.04505334049463272, -0.07491456717252731, -0.02724618837237358, 0.06271106004714966, 0.0012631559511646628, -0.004349054303020239, 0.09244775772094727, -0.11057867854833603, -0.05324712023139, -0.05289844796061516, -0.1077893078327179, -0.09857441484928131, 0.027096757665276527, -0.08378078043460846, -0.023385895416140556, 0.06878791004419327, 0.09100326150655746, -0.034842245280742645, 0.0015853657387197018, 0.0014732928248122334, 0.06440460681915283, 0.022738363593816757, 0.05058227479457855, -0.03952440619468689, 0.04652274027466774, 0.014009122736752033, 0.042836785316467285, -0.0730217769742012, 0.016935473307967186, 0.03725804015994072, -0.04734461009502411, 0.03790557384490967, -0.00612976960837841, 0.020048610866069794, -0.005566291511058807, 0.06071865186095238, 0.0008919141837395728, 0.05768023058772087, -0.08114083856344223, 0.0769069716334343, -0.00020721828332170844, -0.1525188833475113, 0.0041840579360723495, -0.04203982278704643, -0.005510255228728056, -0.05499047785997391, 0.10499993711709976, -0.016424918547272682, -0.019139574840664864, 0.03842858225107193, 0.017408670857548714, -0.005027718376368284, -0.013286874629557133, 0.0066185323521494865, -0.02926350198686123, -0.10888513177633286, 0.010933342389762402, 0.04385789483785629, 0.05708250775933266, 0.08472717553377151, -0.02552773617208004, 0.016462275758385658, -0.0041840579360723495, -0.0058153425343334675, -0.019139574840664864, 0.0379553847014904, -0.059025105088949203, -0.027022041380405426, -0.0029870562721043825, -0.04071985185146332, -0.01570267044007778, 0.022514216601848602, -0.09593447297811508, -0.074466273188591, -0.035215821117162704, 0.03407018631696701, 0.024481721222400665, 0.11625704169273376, -0.06619777530431747, 0.017744889482855797, -0.013324232771992683, 0.043733369559049606, 0.0688377171754837, -0.0799453929066658, 0.06629739701747894, -0.005077528767287731, -0.13100086152553558, -0.11057867854833603, 0.015403809025883675, -0.023933809250593185, 0.018043750897049904, 0.04669707641005516, -0.054641805589199066, -0.041915297508239746, 0.04480428993701935], 'score': 3.52976655960083}, page_content='Vaccines are largely ineffective for patients with established cancer, as advanced disease requires potent and sustained activation of CD8(+) cytotoxic T lymphocytes (CTLs) to kill tumor cells and clear the disease. Recent studies have found that subsets of dendritic cells (DCs) specialize in antigen cross-presentation and in the production of cytokines, which regulate both CTLs and T regulatory (Treg) cells that shut down effector T cell responses. Here, we addressed the hypothesis that coordinated regulation of a DC network, and plasmacytoid DCs (pDCs) and CD8(+) DCs in particular, could enhance host immunity in mice. We used functionalized biomaterials incorporating various combinations of an inflammatory cytokine, immune danger signal, and tumor lysates to control the activation and localization of host DC populations in situ. The numbers of pDCs and CD8(+) DCs, and the endogenous production of interleukin-12, all correlated strongly with the magnitude of protective antitumor immunity and the generation of potent CD8(+) CTLs. Vaccination by this method maintained local and systemic CTL responses for extended periods while inhibiting FoxP3 Treg activity during antigen clearance, resulting in complete regression of distant and established melanoma tumors. The efficacy of this vaccine as a monotherapy against large invasive tumors may be a result of the local activity of pDCs and CD8(+) DCs induced by persistent danger and antigen signaling at the vaccine site. These results indicate that a critical pattern of DC subsets correlates with the evolution of therapeutic antitumor responses and provide a template for future vaccine design.'),\n", + " Document(metadata={'_id': '3770726', 'title': 'Microfluidic platform to evaluate migration of cells from patients with DYT1 dystonia.', 'embedding': [0.01717449352145195, 0.04425951838493347, 0.012141804210841656, 0.09679657965898514, -0.04856721684336662, 0.00971344392746687, -0.0068627591244876385, 0.005148828960955143, 0.023087024688720703, -0.038065437227487564, 0.05084776505827904, -0.026592310518026352, -0.009945721365511417, -0.03395482152700424, -0.018159916624426842, 0.03952949121594429, 0.045836191624403, -0.12117872387170792, 0.0071196723729372025, 0.10451102256774902, 0.11543512344360352, 0.013056838884949684, -0.014168958179652691, -0.05087592080235481, 0.05107300356030464, -0.040486760437488556, 0.06638927757740021, -0.04527309164404869, 0.011121189221739769, -0.06520676612854004, 0.025142334401607513, -0.05346617102622986, 0.01766720600426197, -0.06678344309329987, -0.05290307477116585, 0.06988048553466797, 0.09882372617721558, 0.12714757025241852, -0.06959893554449081, 0.04501969739794731, 0.050059426575899124, -0.045610953122377396, 0.00763701880350709, 0.10445471107959747, -0.03271600231528282, -0.038938239216804504, -0.030688850209116936, -0.030801469460129738, 0.060476742684841156, 0.05239628627896309, -0.023255955427885056, 0.022904017940163612, -0.05757678672671318, 0.018779324367642403, -0.06261651962995529, 0.031308259814977646, 0.009762714616954327, 0.020384153351187706, 0.0074962442740798, 0.0071407887153327465, 0.02335449680685997, -0.059913646429777145, 0.1428017020225525, -0.06137770041823387, 0.010684788227081299, 0.00864355731755495, -0.13998620212078094, 0.01542888954281807, 0.009600823745131493, 0.036319833248853683, 0.013774788938462734, -0.06323592364788055, 0.07427264750003815, -0.10670710355043411, 0.0034595343749970198, -0.030829625204205513, 0.03840329498052597, 0.055662255734205246, -0.008460549637675285, 0.09048987925052643, 0.040064435452222824, -0.10192076861858368, -0.0802977979183197, 0.011100072413682938, -0.02066570334136486, -0.00722877262160182, 0.005071402993053198, -0.11076141148805618, -0.08756176382303238, 0.012817522510886192, -0.03814990073442459, 0.014626475051045418, -0.05901268869638443, 0.1317649781703949, 0.05219919979572296, -0.011114150285720825, 0.017962832003831863, -0.07663766294717789, 0.0027890957426279783, -0.0314771868288517, 0.0634048581123352, 0.04913031682372093, -0.018385155126452446, 0.021749667823314667, 0.11380214244127274, -0.041500333696603775, -0.12478255480527878, -0.00424435269087553, 0.020933175459504128, 0.08035410940647125, 0.1545141339302063, -0.020158914849162102, -0.028267528861761093, 0.09538882970809937, 0.06931738555431366, -0.048933230340480804, -0.03851591423153877, -0.0691484585404396, -0.0069437045603990555, 0.04462553188204765, -0.07810171693563461, 0.076975516974926, 0.04797596484422684, -0.009882372803986073, 0.08677342534065247, -0.09172869473695755, -0.006341893225908279, 0.006764216814190149, -0.20327843725681305, -0.09364322572946548, 0.0516924113035202, -0.012479662895202637, 0.009537475183606148, -0.059237927198410034, -0.10186445713043213, -0.0012669708812609315, 0.016020143404603004, 0.13390474021434784, -0.03640429675579071, 0.08300066739320755, -0.023396728560328484, -0.039247941225767136, 0.10817115753889084, 0.047807034105062485, -0.03857222571969032, 0.0009871814399957657, 0.010325812734663486, 0.13615714013576508, 0.07404740899801254, 0.1146467849612236, 0.01304979994893074, 0.0031111175194382668, 0.01592160016298294, 0.006711426191031933, 0.03260338306427002, -0.003283566329628229, 0.08823748677968979, 0.1264718472957611, -0.019469119608402252, -0.12512041628360748, -0.08142399787902832, -0.019131259992718697, -0.0855909213423729, -0.03280046954751015, -0.0315898060798645, 0.09268596023321152, -0.08209971338510513, -0.03035099245607853, -0.10693234205245972, -0.04676530510187149, -0.045864347368478775, -0.02835199236869812, -0.126359224319458, 0.009403739124536514, -0.06013888493180275, -0.08722390979528427, 0.0009739839006215334, -0.0033662712667137384, -0.014823559671640396, 0.03372957929968834, -0.027366571128368378, 0.09696550667285919, 0.058731138706207275, -0.02241130731999874, -0.02372051030397415, -0.007313237525522709, -0.0031498305033892393, 0.12455731630325317, -0.00918553862720728, 0.0010672470089048147, -0.009157383814454079, 0.04558279737830162, 0.05695737898349762, -0.008573169820010662, -0.0031551094725728035, -0.038684844970703125, 0.15237437188625336, 0.04003627970814705, 0.031139329075813293, -0.06706499308347702, 0.02947818860411644, -0.04769441485404968, -0.07956577092409134, -0.08423949033021927, -0.04045860469341278, 0.06948631256818771, -0.0025568176060914993, 0.03646060824394226, -0.0014930899487808347, 0.0032342951744794846, 0.035306256264448166, 0.08812486380338669, -0.06278544664382935, 0.06503783911466599, 0.03035099245607853, 0.003980400040745735, -0.04403427615761757, 0.0970781221985817, 0.10805854201316833, -0.05470498651266098, -0.03941687196493149, 0.06486891210079193, 0.08480258285999298, 0.17489829659461975, -0.08705497533082962, -0.017695359885692596, 0.05737970396876335, -0.03691108524799347, -0.05507100000977516, -0.05326908826828003, 0.040374137461185455, 0.07534253597259521, 0.017582740634679794, -0.06926107406616211, 0.007545515429228544, 0.030998554080724716, -0.01624538190662861, -0.05312831327319145, 0.11577298492193222, -0.08097352087497711, 0.022256454452872276, 0.0473284013569355, -0.059237927198410034, -0.10873425751924515, -0.00714782765135169, -0.04772257059812546, -0.0747794359922409, -0.05794280394911766, 0.03615090250968933, -0.045864347368478775, -0.08063565939664841, 0.08159292489290237, 0.04014889895915985, -0.047609951347112656, -0.011142305098474026, -0.004437917377799749], 'score': 3.4964065551757812}, page_content=\"BACKGROUND Microfluidic platforms for quantitative evaluation of cell biologic processes allow low cost and time efficient research studies of biological and pathological events, such as monitoring cell migration by real-time imaging. In healthy and disease states, cell migration is crucial in development and wound healing, as well as to maintain the body's homeostasis. NEW METHOD The microfluidic chambers allow precise measurements to investigate whether fibroblasts carrying a mutation in the TOR1A gene, underlying the hereditary neurologic disease--DYT1 dystonia, have decreased migration properties when compared to control cells. RESULTS We observed that fibroblasts from DYT1 patients showed abnormalities in basic features of cell migration, such as reduced velocity and persistence of movement. COMPARISON WITH EXISTING METHOD The microfluidic method enabled us to demonstrate reduced polarization of the nucleus and abnormal orientation of nuclei and Golgi inside the moving DYT1 patient cells compared to control cells, as well as vectorial movement of single cells. CONCLUSION We report here different assays useful in determining various parameters of cell migration in DYT1 patient cells as a consequence of the TOR1A gene mutation, including a microfluidic platform, which provides a means to evaluate real-time vectorial movement with single cell resolution in a three-dimensional environment.\")]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "full_text_search(db[CORPUS_COLLECTION_NAME], \"0-dimensional biomaterials show inductive properties\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QFdAtnF0RQ_H" + }, + "source": [ + "### Vector Search LangChain<>MongoDB Integration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "DrtO8trFRejZ" + }, + "outputs": [], + "source": [ + "from langchain_mongodb import MongoDBAtlasVectorSearch\n", + "from langchain_openai import OpenAIEmbeddings\n", + "\n", + "# Initialize embeddings model\n", + "embedding_model = OpenAIEmbeddings(model=EMBEDDING_MODEL, dimensions=EMBEDDING_DIMENSION_SIZE)\n", + "\n", + "# Initialize vector store\n", + "vector_store = MongoDBAtlasVectorSearch.from_connection_string(\n", + " connection_string=MONGO_URI,\n", + " namespace=f\"{DB_NAME}.{CORPUS_COLLECTION_NAME}\",\n", + " embedding=embedding_model,\n", + " index_name=ATLAS_VECTOR_SEARCH_INDEX,\n", + " text_key=\"text\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "xQrTmWl4RuQP" + }, + "outputs": [], + "source": [ + "# Search functions\n", + "def vector_search(query: str, top_k: int = 10) -> List[Tuple[Any, float]]:\n", + " return vector_store.similarity_search_with_score(query=query, k=top_k)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "9YJxAyprRvf8", + "outputId": "67014648-28d1-46d8-85c7-61d1f13b946a" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(Document(metadata={'_id': '4346436', 'title': 'Nonlinear Elasticity in Biological Gels'}, page_content='Unlike most synthetic materials, biological materials often stiffen as they are deformed. This nonlinear elastic response, critical for the physiological function of some tissues, has been documented since at least the 19th century, but the molecular structure and the design principles responsible for it are unknown. Current models for this response require geometrically complex ordered structures unique to each material. In this Article we show that a much simpler molecular theory accounts for strain stiffening in a wide range of molecularly distinct biopolymer gels formed from purified cytoskeletal and extracellular proteins. This theory shows that systems of semi-flexible chains such as filamentous proteins arranged in an open crosslinked meshwork invariably stiffen at low strains without the need for a specific architecture or multiple elements with different intrinsic stiffnesses.'),\n", + " 0.7601195573806763),\n", + " (Document(metadata={'_id': '927561', 'title': 'Emergent structures and dynamics of cell colonies by contact inhibition of locomotion'}, page_content='Cells in tissues can organize into a broad spectrum of structures according to their function. Drastic changes of organization, such as epithelial-mesenchymal transitions or the formation of spheroidal aggregates, are often associated either to tissue morphogenesis or to cancer progression. Here, we study the organization of cell colonies by means of simulations of self-propelled particles with generic cell-like interactions. The interplay between cell softness, cell-cell adhesion, and contact inhibition of locomotion (CIL) yields structures and collective dynamics observed in several existing tissue phenotypes. These include regular distributions of cells, dynamic cell clusters, gel-like networks, collectively migrating monolayers, and 3D aggregates. We give analytical predictions for transitions between noncohesive, cohesive, and 3D cell arrangements. We explicitly show how CIL yields an effective repulsion that promotes cell dispersal, thereby hindering the formation of cohesive tissues. Yet, in continuous monolayers, CIL leads to collective cell motion, ensures tensile intercellular stresses, and opposes cell extrusion. Thus, our work highlights the prominent role of CIL in determining the emergent structures and dynamics of cell colonies.'),\n", + " 0.7536574006080627),\n", + " (Document(metadata={'_id': '19685306', 'title': 'Orientationally invariant indices of axon diameter and density from diffusion MRI.'}, page_content='This paper proposes and tests a technique for imaging orientationally invariant indices of axon diameter and density in white matter using diffusion magnetic resonance imaging. Such indices potentially provide more specific markers of white matter microstructure than standard indices from diffusion tensor imaging. Orientational invariance allows for combination with tractography and presents new opportunities for mapping brain connectivity and quantifying disease processes. The technique uses a four-compartment tissue model combined with an optimized multishell high-angular-resolution pulsed-gradient-spin-echo acquisition. We test the method in simulation, on fixed monkey brains using a preclinical scanner and on live human brains using a clinical 3T scanner. The human data take about one hour to acquire. The simulation experiments show that both monkey and human protocols distinguish distributions of axon diameters that occur naturally in white matter. We compare the axon diameter index with the mean axon diameter weighted by axon volume. The index differs from this mean and is protocol dependent, but correlation is good for the monkey protocol and weaker, but discernible, for the human protocol where greater diffusivity and lower gradient strength limit sensitivity to only the largest axons. Maps of axon diameter and density indices from the monkey and human data in the corpus callosum and corticospinal tract reflect known trends from histology. The results show orientationally invariant sensitivity to natural axon diameter distributions for the first time with both specialist and clinical hardware. This demonstration motivates further refinement, validation, and evaluation of the precise nature of the indices and the influence of potential confounds.'),\n", + " 0.742658793926239),\n", + " (Document(metadata={'_id': '17388232', 'title': 'Mechanical regulation of cell function with geometrically modulated elastomeric substrates'}, page_content='We report the establishment of a library of micromolded elastomeric micropost arrays to modulate substrate rigidity independently of effects on adhesive and other material surface properties. We demonstrated that micropost rigidity impacts cell morphology, focal adhesions, cytoskeletal contractility and stem cell differentiation. Furthermore, early changes in cytoskeletal contractility predicted later stem cell fate decisions in single cells.'),\n", + " 0.7384290099143982),\n", + " (Document(metadata={'_id': '14082855', 'title': 'Inflammatory Reaction as Determinant of Foreign Body Reaction Is an Early and Susceptible Event after Mesh Implantation'}, page_content='PURPOSE To investigate and relate the ultrashort-term and long-term courses of determinants for foreign body reaction as biocompatibility predictors for meshes in an animal model. MATERIALS AND METHODS Three different meshes (TVT, UltraPro, and PVDF) were implanted in sheep. Native and plasma coated meshes were placed bilaterally: (a) interaperitoneally, (b) as fascia onlay, and (c) as muscle onlay (fascia sublay). At 5 min, 20 min, 60 min, and 120 min meshes were explanted and histochemically investigated for inflammatory infiltrate, macrophage infiltration, vessel formation, myofibroblast invasion, and connective tissue accumulation. The results were related to long-term values over 24 months. RESULTS Macrophage invasion reached highest extents with up to 60% in short-term and decreased within 24 months to about 30%. Inflammatory infiltrate increased within the first 2 hours, the reached levels and the different extents and ranking among the investigated meshes remained stable during long-term follow up. For myofibroblasts, connective tissue, and CD31+ cells, no activity was detected during the first 120 min. CONCLUSION The local inflammatory reaction is an early and susceptible event after mesh implantation. It cannot be influenced by prior plasma coating and does not depend on the localisation of implantation.'),\n", + " 0.7378800511360168),\n", + " (Document(metadata={'_id': '28071965', 'title': 'A Balance between Secreted Inhibitors and Edge Sensing Controls Gastruloid Self-Organization.'}, page_content='The earliest aspects of human embryogenesis remain mysterious. To model patterning events in the human embryo, we used colonies of human embryonic stem cells (hESCs) grown on micropatterned substrate and differentiated with BMP4. These gastruloids recapitulate the embryonic arrangement of the mammalian germ layers and provide an assay to assess the structural and signaling mechanisms patterning the human gastrula. Structurally, high-density hESCs localize their receptors to transforming growth factor β at their lateral side in the center of the colony while maintaining apical localization of receptors at the edge. This relocalization insulates cells at the center from apically applied ligands while maintaining response to basally presented ones. In addition, BMP4 directly induces the expression of its own inhibitor, NOGGIN, generating a reaction-diffusion mechanism that underlies patterning. We develop a quantitative model that integrates edge sensing and inhibitors to predict human fate positioning in gastruloids and, potentially, the human embryo.'),\n", + " 0.7353475689888),\n", + " (Document(metadata={'_id': '39291138', 'title': 'Integration of Smad and MAPK pathways: a link and a linker revisited.'}, page_content='Cells develop by reading mixed signals. Nowhere is this clearer than in the highly dynamic processes that propel embryogenesis, when critical cell-fate decisions are made swiftly in response to well-orchestrated growthfactor combinations. Learning how diverse signaling pathways are integrated is therefore essential for understanding physiology. This requires the identification, in tangible molecular terms, of key nodes for pathway integration that operate in vivo. A report in this issue, on the integration of Smad and Ras/MAPK pathways during neural induction (Pera et al. 2003), provides timely insights into the relevance of one such node. Pera et al. (2003) report that FGF8 and IGF2—two growth factors that activate the Ras/MAPK pathway— favor neural differentiation and mesoderm dorsalization in Xenopus by inhibiting BMP (Bone Morphogenetic Protein) signaling. Mesoderm is formed from ectoderm in response to Nodal-related signals from the endoderm at the blastula stage and beyond (Fig. 1; for review, see De Robertis et al. 2000). BMP induces differentiation of ectoderm into epidermal cell fates at the expense of neural fates, and it ventralizes the mesoderm at the expense of dorsal fates (for review, see Weinstein and HemmatiBrivanlou 1999; De Robertis et al. 2000). Accordingly, neural differentiation and dorsal mesoderm formation are favored when BMP signaling is attenuated. Noggin, Chordin, Cerberus, and Follistatin, secreted by the Spemann organizer on the dorsal side at the gastrula stage, facilitate the formation of neural tissue by sequestering BMP (Weinstein and Hemmati-Brivanlou 1999; De Robertis et al. 2000). Experimentally blocking BMP signaling with a dominant-negative BMP receptor has a similar effect of promoting ectoderm neuralization (Weinstein and Hemmati-Brivanlou 1999). As it turns out, neural induction can also be achieved with FGF (fibroblast growth factor; Kengaku and Okamoto 1993; Lamb and Harland 1995; Hongo et al. 1999; Hardcastle et al. 2000; Streit et al. 2000; Wilson et al. 2000) and IGF (insulin-like growth factor; Pera et al. 2001; Richard-Parpaillon et al. 2002). Injection of transcripts encoding FGF8 or IFG2 into one animal-pole blastomere of a fourto eight-cell embryo results in an expanded neural plate at the injected side (Pera et al. 2003). Surprisingly, expression of a dominant-negative FGF receptor prevents neuralization of ectoderm explants by the BMP blocker Noggin (Launay et al. 1996). Likewise, the potent neuralizing effect of Chordin can be blocked by a dominant-negative FGF receptor or a morpholino oligonucleotide targeting the IGF receptor (Pera et al. 2003). Thus, the neuralizing effect of BMP inhibitors is somehow tied to FGF and IFG signaling. The question is, how? Because FGF8 and IFG2 activate MAPK, Pera et al. (2003) took heed from previous work showing that MAPK inhibits the BMP signal-transduction factor Smad1 (Kretzschmar et al. 1997a). Smad1 is directly phosphorylated by the BMP receptor, resulting in Smad1 activation (Kretzschmar et al. 1997b), and by MAPK in response to EGF, resulting in Smad1 inhibition (Kretzschmar et al. 1997a; Fig. 2). Smad transcription factors mediate gene responses to the entire TGF (Transforming Growth Factor) family, to which the BMPs belong (for review, see Massague 2000; Derynck and Zhang 2003). Smads 1, 5, and 8 act primarily downstream of BMP receptors and Smads 2 and 3 downstream of TGF , Activin and Nodal receptors. Smad proteins have two conserved globular domains—the MH1 and MH2 domains (Fig. 2). The MH1 domain is involved in DNA binding and the MH2 domain in binding to cytoplasmic retention factors, activated receptors, nucleoporins in the nuclear pore, and DNA-binding cofactors, coactivators, and corepressors in the nucleus (for review, see Shi and Massague 2003). Receptor-mediated phosphorylation occurs at the carboxy-terminal sequence SXS. This enables the nuclear accumulation of Smads and their association with the shared partner Smad4 to form transcriptional complexes that are interpreted by the cell as a function of the context (Massague 2000). Between the MH1 and MH2 domains lies a linker region of variable sequence and length. Attention was drawn to this region when it was found that EGF (epidermal growth factor), a classical activator of the Ras/ MAPK pathway, causes phosphorylation of the Smad1 linker at four MAPK sites (PXSP sequences; Kretzschmar et al. 1997a). This prevents the nuclear localization of Smad1 and inhibits BMP signaling. Mutation of these E-MAIL j-massague@ski.mskcc.org; FAX (212) 717-3298. Article and publication are at http://www.genesdev.org/cgi/doi/10.1101/ gad.1167003.'),\n", + " 0.7275398969650269),\n", + " (Document(metadata={'_id': '43990286', 'title': 'Cell and biomolecule delivery for tissue repair and regeneration in the central nervous system.'}, page_content='Tissue engineering frequently involves cells and scaffolds to replace damaged or diseased tissue. It originated, in part, as a means of effecting the delivery of biomolecules such as insulin or neurotrophic factors, given that cells are constitutive producers of such therapeutic agents. Thus cell delivery is intrinsic to tissue engineering. Controlled release of biomolecules is also an important tool for enabling cell delivery since the biomolecules can enable cell engraftment, modulate inflammatory response or otherwise benefit the behavior of the delivered cells. We describe advances in cell and biomolecule delivery for tissue regeneration, with emphasis on the central nervous system (CNS). In the first section, the focus is on encapsulated cell therapy. In the second section, the focus is on biomolecule delivery in polymeric nano/microspheres and hydrogels for the nerve regeneration and endogenous cell stimulation. In the third section, the focus is on combination strategies of neural stem/progenitor cell or mesenchymal stem cell and biomolecule delivery for tissue regeneration and repair. In each section, the challenges and potential solutions associated with delivery to the CNS are highlighted.'),\n", + " 0.7260926961898804),\n", + " (Document(metadata={'_id': '7583104', 'title': 'IDEAL in meshes for prolapse, urinary incontinence, and hernia repair.'}, page_content='PURPOSE Mesh surgeries are counted among the most frequently applied surgical procedures. Despite global spread of mesh applying surgeries, there is no current systematic analysis of incidence and possible prevention of adverse events after mesh implantation. MATERIALS AND METHODS Based on the recommendations of IDEAL an in vitro test system for biocompatibility of surgical meshes has been generated (Innovation). Coating strategies for biocompatibility optimization have been developed (Development). The native and modified alloplastic materials have been tested in an animal model over 2 years (Exploration and Assessment and Long-term study). RESULTS In 3 meshes, implanted in sheep and explanted at 4 different time points (a, 3 months; b, 6 months; c, 12 months; and d, 24 months) over 24 months, thickness of inflammatory tissue (TVT a, 35 µm; b, 32 µm; c, 33 µm; d, 28 µm; UltraPro, a, 25 µm; b, 24 µm; c, 21 µm; d, 22 µm; PVDF a, 20 µm; b, 21 µm; c, 14 µm; d, 15µm), connective tissue (TVT a, 37 µm; b, 36 µm; c, 43 µm; d, 41 µm; UltraPro a, 33 µm; b, 32 µm; c, 40 µm; d, 38 µm; PVDF a, 25 µm; b, 22 µm; c, 22 µm; d, 24 µm), and macrophage infiltration (TVT a, 36%; b, 33%; c, 23%; d, 20%; UltraPro a, 34%; b, 28%; c, 25%; d, 22%; PVDF a, 24%; b, 18%; c, 18%; d, 16%) revealed comparable ranking characteristics at every time point after explantation. The in vivo performance of these meshes in a sheep model was predictable with a previously developed in vitro test system. Coating of meshes with autologous plasma prior to implantation seems to have a positive effect on the meshes biocompatibility. CONCLUSION We have applied IDEAL criteria on a new innovation for surgical meshes. The results permit the generation of a ranking of currently available meshes with potential to optimize future meshes.'),\n", + " 0.7255579829216003),\n", + " (Document(metadata={'_id': '18909530', 'title': 'Contractile forces sustain and polarize hematopoiesis from stem and progenitor cells.'}, page_content='Self-renewal and differentiation of stem cells depend on asymmetric division and polarized motility processes that in other cell types are modulated by nonmuscle myosin-II (MII) forces and matrix mechanics. Here, mass spectrometry-calibrated intracellular flow cytometry of human hematopoiesis reveals MIIB to be a major isoform that is strongly polarized in hematopoietic stem cells and progenitors (HSC/Ps) and thereby downregulated in differentiated cells via asymmetric division. MIIA is constitutive and activated by dephosphorylation during cytokine-triggered differentiation of cells grown on stiff, endosteum-like matrix, but not soft, marrow-like matrix. In vivo, MIIB is required for generation of blood, while MIIA is required for sustained HSC/P engraftment. Reversible inhibition of both isoforms in culture with blebbistatin enriches for long-term hematopoietic multilineage reconstituting cells by 5-fold or more as assessed in vivo. Megakaryocytes also become more polyploid, producing 4-fold more platelets. MII is thus a multifunctional node in polarized division and niche sensing.'),\n", + " 0.7254542708396912)]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector_search(\"0-dimensional biomaterials show inductive properties\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "8fdjA-VQRav-" + }, + "source": [ + "### Hybrid Search LangChain<>MongoDB Integration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "ReA2Jpbntzmk" + }, + "outputs": [], + "source": [ + "from langchain_mongodb.retrievers import MongoDBAtlasHybridSearchRetriever\n", + "\n", + "\n", + "def hybrid_search(query: str, top_k: int = 10) -> List[Document]:\n", + " hybrid_search = MongoDBAtlasHybridSearchRetriever(\n", + " vectorstore=vector_store,\n", + " search_index_name=\"text_search_index\",\n", + " top_k=top_k\n", + " )\n", + " return hybrid_search.get_relevant_documents(query)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mJ0Fa-6tuAoM", + "outputId": "8b0110de-e499-4e1d-eae4-1520d9c5b286" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[Document(metadata={'_id': '4346436', 'title': 'Nonlinear Elasticity in Biological Gels', 'vector_score': 0.01639344262295082, 'rank': 0, 'fulltext_score': 0, 'score': 0.01639344262295082}, page_content='Unlike most synthetic materials, biological materials often stiffen as they are deformed. This nonlinear elastic response, critical for the physiological function of some tissues, has been documented since at least the 19th century, but the molecular structure and the design principles responsible for it are unknown. Current models for this response require geometrically complex ordered structures unique to each material. In this Article we show that a much simpler molecular theory accounts for strain stiffening in a wide range of molecularly distinct biopolymer gels formed from purified cytoskeletal and extracellular proteins. This theory shows that systems of semi-flexible chains such as filamentous proteins arranged in an open crosslinked meshwork invariably stiffen at low strains without the need for a specific architecture or multiple elements with different intrinsic stiffnesses.'),\n", + " Document(metadata={'_id': '10608397', 'title': 'High-performance neuroprosthetic control by an individual with tetraplegia.', 'score': 0.01639344262295082, 'fulltext_score': 0.01639344262295082, 'rank': 0, 'vector_score': 0}, page_content=\"BACKGROUND Paralysis or amputation of an arm results in the loss of the ability to orient the hand and grasp, manipulate, and carry objects, functions that are essential for activities of daily living. Brain-machine interfaces could provide a solution to restoring many of these lost functions. We therefore tested whether an individual with tetraplegia could rapidly achieve neurological control of a high-performance prosthetic limb using this type of an interface. METHODS We implanted two 96-channel intracortical microelectrodes in the motor cortex of a 52-year-old individual with tetraplegia. Brain-machine-interface training was done for 13 weeks with the goal of controlling an anthropomorphic prosthetic limb with seven degrees of freedom (three-dimensional translation, three-dimensional orientation, one-dimensional grasping). The participant's ability to control the prosthetic limb was assessed with clinical measures of upper limb function. This study is registered with ClinicalTrials.gov, NCT01364480. FINDINGS The participant was able to move the prosthetic limb freely in the three-dimensional workspace on the second day of training. After 13 weeks, robust seven-dimensional movements were performed routinely. Mean success rate on target-based reaching tasks was 91·6% (SD 4·4) versus median chance level 6·2% (95% CI 2·0-15·3). Improvements were seen in completion time (decreased from a mean of 148 s [SD 60] to 112 s [6]) and path efficiency (increased from 0·30 [0·04] to 0·38 [0·02]). The participant was also able to use the prosthetic limb to do skilful and coordinated reach and grasp movements that resulted in clinically significant gains in tests of upper limb function. No adverse events were reported. INTERPRETATION With continued development of neuroprosthetic limbs, individuals with long-term paralysis could recover the natural and intuitive command signals for hand placement, orientation, and reaching, allowing them to perform activities of daily living. FUNDING Defense Advanced Research Projects Agency, National Institutes of Health, Department of Veterans Affairs, and UPMC Rehabilitation Institute.\"),\n", + " Document(metadata={'_id': '40212412', 'title': 'Periosteal bone formation--a neglected determinant of bone strength.', 'score': 0.016129032258064516, 'fulltext_score': 0.016129032258064516, 'rank': 1, 'vector_score': 0}, page_content=\"Life forms that have low body mass can hunt for food on the undersurface of branches or along shear cliff faces quite unperturbed by gravity. For larger animals, the hunt for dinner and the struggle to avoid becoming someone else's meal require rapid movement against gravity. This need is met by the lever function of long bones, three-dimensional masterpieces of biomechanical engineering that, by their material composition and structural design, achieve the contradictory properties of stiffness and flexibility, strength and lightness.1 Material stiffness results from the encrusting of the triple-helical structure of collagen type I with hydroxyapatite crystals, which confers . . .\"),\n", + " Document(metadata={'_id': '927561', 'title': 'Emergent structures and dynamics of cell colonies by contact inhibition of locomotion', 'vector_score': 0.016129032258064516, 'rank': 1, 'fulltext_score': 0, 'score': 0.016129032258064516}, page_content='Cells in tissues can organize into a broad spectrum of structures according to their function. Drastic changes of organization, such as epithelial-mesenchymal transitions or the formation of spheroidal aggregates, are often associated either to tissue morphogenesis or to cancer progression. Here, we study the organization of cell colonies by means of simulations of self-propelled particles with generic cell-like interactions. The interplay between cell softness, cell-cell adhesion, and contact inhibition of locomotion (CIL) yields structures and collective dynamics observed in several existing tissue phenotypes. These include regular distributions of cells, dynamic cell clusters, gel-like networks, collectively migrating monolayers, and 3D aggregates. We give analytical predictions for transitions between noncohesive, cohesive, and 3D cell arrangements. We explicitly show how CIL yields an effective repulsion that promotes cell dispersal, thereby hindering the formation of cohesive tissues. Yet, in continuous monolayers, CIL leads to collective cell motion, ensures tensile intercellular stresses, and opposes cell extrusion. Thus, our work highlights the prominent role of CIL in determining the emergent structures and dynamics of cell colonies.'),\n", + " Document(metadata={'_id': '43385013', 'title': 'Epithelial and mesenchymal subpopulations within normal basal breast cell lines exhibit distinct stem cell/progenitor properties.', 'score': 0.015873015873015872, 'fulltext_score': 0.015873015873015872, 'rank': 2, 'vector_score': 0}, page_content='It has been proposed that epithelial-mesenchymal transition (EMT) in mammary epithelial cells and breast cancer cells generates stem cell features, and that the presence of EMT characteristics in claudin-low breast tumors reveals their origin in basal stem cells. It remains to be determined, however, whether EMT is an inherent property of normal basal stem cells, and if the presence of a mesenchymal-like phenotype is required for the maintenance of all their stem cell properties. We used nontumorigenic basal cell lines as models of normal stem cells/progenitors and demonstrate that these cell lines contain an epithelial subpopulation (\"EpCAM+,\" epithelial cell adhesion molecule positive [EpCAM(pos)]/CD49f(high)) that spontaneously generates mesenchymal-like cells (\"Fibros,\" EpCAM(neg)/CD49f(med/low)) through EMT. Importantly, stem cell/progenitor properties such as regenerative potential, high aldehyde dehydrogenase 1 activity, and formation of three-dimensional acini-like structures predominantly reside within EpCAM+ cells, while Fibros exhibit invasive behavior and mammosphere-forming ability. A gene expression profiling meta-analysis established that EpCAM+ cells show a luminal progenitor-like expression pattern, while Fibros most closely resemble stromal fibroblasts but not stem cells. Moreover, Fibros exhibit partial myoepithelial traits and strong similarities with claudin-low breast cancer cells. Finally, we demonstrate that Slug and Zeb1 EMT-inducers control the progenitor and mesenchymal-like phenotype in EpCAM+ cells and Fibros, respectively, by inhibiting luminal differentiation. In conclusion, nontumorigenic basal cell lines have intrinsic capacity for EMT, but a mesenchymal-like phenotype does not correlate with the acquisition of global stem cell/progenitor features. Based on our findings, we propose that EMT in normal basal cells and claudin-low breast cancers reflects aberrant/incomplete myoepithelial differentiation.'),\n", + " Document(metadata={'_id': '19685306', 'title': 'Orientationally invariant indices of axon diameter and density from diffusion MRI.', 'vector_score': 0.015873015873015872, 'rank': 2, 'fulltext_score': 0, 'score': 0.015873015873015872}, page_content='This paper proposes and tests a technique for imaging orientationally invariant indices of axon diameter and density in white matter using diffusion magnetic resonance imaging. Such indices potentially provide more specific markers of white matter microstructure than standard indices from diffusion tensor imaging. Orientational invariance allows for combination with tractography and presents new opportunities for mapping brain connectivity and quantifying disease processes. The technique uses a four-compartment tissue model combined with an optimized multishell high-angular-resolution pulsed-gradient-spin-echo acquisition. We test the method in simulation, on fixed monkey brains using a preclinical scanner and on live human brains using a clinical 3T scanner. The human data take about one hour to acquire. The simulation experiments show that both monkey and human protocols distinguish distributions of axon diameters that occur naturally in white matter. We compare the axon diameter index with the mean axon diameter weighted by axon volume. The index differs from this mean and is protocol dependent, but correlation is good for the monkey protocol and weaker, but discernible, for the human protocol where greater diffusivity and lower gradient strength limit sensitivity to only the largest axons. Maps of axon diameter and density indices from the monkey and human data in the corpus callosum and corticospinal tract reflect known trends from histology. The results show orientationally invariant sensitivity to natural axon diameter distributions for the first time with both specialist and clinical hardware. This demonstration motivates further refinement, validation, and evaluation of the precise nature of the indices and the influence of potential confounds.'),\n", + " Document(metadata={'_id': '17388232', 'title': 'Mechanical regulation of cell function with geometrically modulated elastomeric substrates', 'vector_score': 0.015625, 'rank': 3, 'fulltext_score': 0, 'score': 0.015625}, page_content='We report the establishment of a library of micromolded elastomeric micropost arrays to modulate substrate rigidity independently of effects on adhesive and other material surface properties. We demonstrated that micropost rigidity impacts cell morphology, focal adhesions, cytoskeletal contractility and stem cell differentiation. Furthermore, early changes in cytoskeletal contractility predicted later stem cell fate decisions in single cells.'),\n", + " Document(metadata={'_id': '10931595', 'title': 'Geometry, epistasis, and developmental patterning.', 'score': 0.015625, 'fulltext_score': 0.015625, 'rank': 3, 'vector_score': 0}, page_content='Developmental signaling networks are composed of dozens of components whose interactions are very difficult to quantify in an embryo. Geometric reasoning enumerates a discrete hierarchy of phenotypic models with a few composite variables whose parameters may be defined by in vivo data. Vulval development in the nematode Caenorhabditis elegans is a classic model for the integration of two signaling pathways; induction by EGF and lateral signaling through Notch. Existing data for the relative probabilities of the three possible terminal cell types in diverse genetic backgrounds as well as timed ablation of the inductive signal favor one geometric model and suffice to fit most of its parameters. The model is fully dynamic and encompasses both signaling and commitment. It then predicts the correlated cell fate probabilities for a cross between any two backgrounds/conditions. The two signaling pathways are combined additively, without interactions, and epistasis only arises from the nonlinear dynamical flow in the landscape defined by the geometric model. In this way, the model quantitatively fits genetic experiments purporting to show mutual pathway repression. The model quantifies the contributions of extrinsic vs. intrinsic sources of noise in the penetrance of mutant phenotypes in signaling hypomorphs and explains available experiments with no additional parameters. Data for anchor cell ablation fix the parameters needed to define Notch autocrine signaling.'),\n", + " Document(metadata={'_id': '27049238', 'title': 'Large deformation of red blood cell ghosts in a simple shear flow.', 'score': 0.015384615384615385, 'fulltext_score': 0.015384615384615385, 'rank': 4, 'vector_score': 0}, page_content='Red blood cells are known to change shape in response to local flow conditions. Deformability affects red blood cell physiological function and the hydrodynamic properties of blood. The immersed boundary method is used to simulate three-dimensional membrane-fluid flow interactions for cells with the same internal and external fluid viscosities. The method has been validated for small deformations of an initially spherical capsule in simple shear flow for both neo-Hookean and the Evans-Skalak membrane models. Initially oblate spheroidal capsules are simulated and it is shown that the red blood cell membrane exhibits asymptotic behavior as the ratio of the dilation modulus to the extensional modulus is increased and a good approximation of local area conservation is obtained. Tank treading behavior is observed and its period calculated.'),\n", + " Document(metadata={'_id': '14082855', 'title': 'Inflammatory Reaction as Determinant of Foreign Body Reaction Is an Early and Susceptible Event after Mesh Implantation', 'vector_score': 0.015384615384615385, 'rank': 4, 'fulltext_score': 0, 'score': 0.015384615384615385}, page_content='PURPOSE To investigate and relate the ultrashort-term and long-term courses of determinants for foreign body reaction as biocompatibility predictors for meshes in an animal model. MATERIALS AND METHODS Three different meshes (TVT, UltraPro, and PVDF) were implanted in sheep. Native and plasma coated meshes were placed bilaterally: (a) interaperitoneally, (b) as fascia onlay, and (c) as muscle onlay (fascia sublay). At 5 min, 20 min, 60 min, and 120 min meshes were explanted and histochemically investigated for inflammatory infiltrate, macrophage infiltration, vessel formation, myofibroblast invasion, and connective tissue accumulation. The results were related to long-term values over 24 months. RESULTS Macrophage invasion reached highest extents with up to 60% in short-term and decreased within 24 months to about 30%. Inflammatory infiltrate increased within the first 2 hours, the reached levels and the different extents and ranking among the investigated meshes remained stable during long-term follow up. For myofibroblasts, connective tissue, and CD31+ cells, no activity was detected during the first 120 min. CONCLUSION The local inflammatory reaction is an early and susceptible event after mesh implantation. It cannot be influenced by prior plasma coating and does not depend on the localisation of implantation.')]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hybrid_search(\"0-dimensional biomaterials show inductive properties\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "28LA_rDCToLz" + }, + "source": [ + "# Information Retrieval Evaluation Process Begins\n", + "\n", + "\n", + "---\n", + "\n", + "\n", + "\n", + "---\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "W4n7ELsGxWVV" + }, + "source": [ + "# **Step 6: Custom Retrieval Class For Lexical Search**\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Y9IcUtnRvGrx" + }, + "outputs": [], + "source": [ + "from typing import Dict\n", + "\n", + "from beir.retrieval.search.base import BaseSearch\n", + "\n", + "\n", + "class MongoDBSearch(BaseSearch):\n", + " def __init__(self, collection, search_index_name, search_field=\"text\", batch_size=128):\n", + " self.collection = collection\n", + " self.search_index_name = search_index_name\n", + " self.search_field = search_field\n", + " self.batch_size = batch_size\n", + "\n", + " def search(self,\n", + " corpus: Dict[str, Dict[str, str]],\n", + " queries: Dict[str, str],\n", + " top_k: int,\n", + " score_function: str = \"dot\",\n", + " **kwargs) -> Dict[str, Dict[str, float]]:\n", + " results = {}\n", + " for query_id, query_text in queries.items():\n", + " full_text_search = MongoDBAtlasFullTextSearchRetriever(\n", + " collection=self.collection,\n", + " search_index_name=self.search_index_name,\n", + " search_field=self.search_field,\n", + " top_k=top_k\n", + " )\n", + " documents = full_text_search.get_relevant_documents(query_text)\n", + " results[query_id] = {doc.metadata['_id']: doc.metadata['score'] for doc in documents}\n", + " return results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "OAhWdRiFx2QD" + }, + "outputs": [], + "source": [ + "model = MongoDBSearch(db[CORPUS_COLLECTION_NAME], TEXT_SEARCH_INDEX)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "ETzC-2k5zAwl" + }, + "outputs": [], + "source": [ + "retriever = EvaluateRetrieval(model)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "j7a_ORZJvG1h" + }, + "outputs": [], + "source": [ + "# Retrieve results\n", + "results = retriever.retrieve(corpus, queries)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KvPjPmI3DxMV", + "outputId": "d12aa9fd-1a7a-4e87-b5db-9f31e7916248" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sample of retrieved results:\n", + "Query ID: 1\n", + "Query text: 0-dimensional biomaterials show inductive properties.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 10608397, Score: 6.045361518859863\n", + " Doc ID: 40212412, Score: 4.411067962646484\n", + " Doc ID: 43385013, Score: 4.344019412994385\n", + "\n", + "Query ID: 3\n", + "Query text: 1,000 genomes project enables mapping of genetic sequence variation consisting of rare variants with larger penetrance effects than common variants.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 3672261, Score: 14.99349308013916\n", + " Doc ID: 14717500, Score: 13.623835563659668\n", + " Doc ID: 23389795, Score: 13.595733642578125\n", + "\n", + "Query ID: 5\n", + "Query text: 1/2000 in UK have abnormal PrP positivity.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 13734012, Score: 9.427136421203613\n", + " Doc ID: 18617259, Score: 7.08165979385376\n", + " Doc ID: 42240424, Score: 5.731115818023682\n", + "\n", + "Query ID: 13\n", + "Query text: 5% of perinatal mortality is due to low birth weight.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 1263446, Score: 9.440444946289062\n", + " Doc ID: 17450673, Score: 9.43663501739502\n", + " Doc ID: 7662395, Score: 9.31999397277832\n", + "\n", + "Query ID: 36\n", + "Query text: A deficiency of vitamin B12 increases blood levels of homocysteine.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 42441846, Score: 13.356172561645508\n", + " Doc ID: 33409100, Score: 10.587646484375\n", + " Doc ID: 18557974, Score: 10.070034980773926\n", + "\n" + ] + } + ], + "source": [ + "# Print some results for inspection\n", + "print(\"Sample of retrieved results:\")\n", + "for query_id, doc_scores in list(results.items())[:5]: # First 5 queries\n", + " print(f\"Query ID: {query_id}\")\n", + " print(f\"Query text: {queries[query_id]}\")\n", + " print(\"Top 3 retrieved documents:\")\n", + " for doc_id, score in list(doc_scores.items())[:3]:\n", + " print(f\" Doc ID: {doc_id}, Score: {score}\")\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "6_du_owvD2r5" + }, + "outputs": [], + "source": [ + "# Evaluate the model\n", + "metrics = retriever.evaluate(qrels, results, retriever.k_values)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-bLj2_NnEtZ_", + "outputId": "22302b4e-d1a0-44c4-8d35-ea0633b51af1" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "NDCG:\n", + " NDCG@1: 0.5300\n", + " NDCG@3: 0.6123\n", + " NDCG@5: 0.6322\n", + " NDCG@10: 0.6506\n", + " NDCG@100: 0.6749\n", + " NDCG@1000: 0.6860\n", + "\n", + "MAP:\n", + " MAP@1: 0.5115\n", + " MAP@3: 0.5854\n", + " MAP@5: 0.5979\n", + " MAP@10: 0.6071\n", + " MAP@100: 0.6124\n", + " MAP@1000: 0.6129\n", + "\n", + "Recall:\n", + " Recall@1: 0.5115\n", + " Recall@3: 0.6673\n", + " Recall@5: 0.7151\n", + " Recall@10: 0.7676\n", + " Recall@100: 0.8752\n", + " Recall@1000: 0.9617\n", + "\n", + "Precision:\n", + " P@1: 0.5300\n", + " P@3: 0.2367\n", + " P@5: 0.1547\n", + " P@10: 0.0847\n", + " P@100: 0.0099\n", + " P@1000: 0.0011\n" + ] + } + ], + "source": [ + "ndcg, _map, recall, precision = metrics\n", + "\n", + "lexical_search_metric_dicts = [ndcg, _map, recall, precision]\n", + "\n", + "for name, metric_dict in zip(metric_names, lexical_search_metric_dicts):\n", + " print(f\"\\n{name}:\")\n", + " for k, score in metric_dict.items():\n", + " print(f\" {k}: {score:.4f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "rQZAvU1Oxzxe" + }, + "source": [ + "# **Step 7: Custom Retrieval Class For Vector Search**\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "hNSDBi1yx3v2" + }, + "outputs": [], + "source": [ + "class MongoDBVectorSearch(BaseSearch):\n", + " def __init__(self, vector_store: MongoDBAtlasVectorSearch, embedding_model: OpenAIEmbeddings, batch_size=128):\n", + " self.vector_store = vector_store\n", + " self.embedding_model = embedding_model\n", + " self.batch_size = batch_size\n", + "\n", + " def search(self,\n", + " corpus: Dict[str, Dict[str, str]],\n", + " queries: Dict[str, str],\n", + " top_k: int,\n", + " score_function: str = \"dot\",\n", + " **kwargs) -> Dict[str, Dict[str, float]]:\n", + " results = {}\n", + " for query_id, query_text in queries.items():\n", + " vector_results = self.vector_store.similarity_search_with_score(query=query_text, k=top_k)\n", + " # Convert to the format expected by BEIR\n", + " results[query_id] = {str(doc.metadata.get('_id', i)): score for i, (doc, score) in enumerate(vector_results)}\n", + " return results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "4eSbP11Gx-__" + }, + "outputs": [], + "source": [ + "mongodb_vector_search = MongoDBVectorSearch(vector_store, embedding_model)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "cUf0-vhlyA53" + }, + "outputs": [], + "source": [ + "vector_search_retriever = EvaluateRetrieval(mongodb_vector_search)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "k9YFG61zyEox" + }, + "outputs": [], + "source": [ + "vector_search_eval_results = vector_search_retriever.retrieve(corpus, queries)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "S6VnMRLQikgt", + "outputId": "1394db41-8473-498d-db55-c0a6d63b8135" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sample of retrieved results:\n", + "Query ID: 1\n", + "Query text: 0-dimensional biomaterials show inductive properties.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 4346436, Score: 0.755730390548706\n", + " Doc ID: 14082855, Score: 0.7475494146347046\n", + " Doc ID: 927561, Score: 0.7456868886947632\n", + "\n", + "Query ID: 3\n", + "Query text: 1,000 genomes project enables mapping of genetic sequence variation consisting of rare variants with larger penetrance effects than common variants.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 2739854, Score: 0.8083912134170532\n", + " Doc ID: 41782935, Score: 0.8060566782951355\n", + " Doc ID: 1388704, Score: 0.8057119846343994\n", + "\n", + "Query ID: 5\n", + "Query text: 1/2000 in UK have abnormal PrP positivity.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 13734012, Score: 0.8474858999252319\n", + " Doc ID: 18617259, Score: 0.8069760799407959\n", + " Doc ID: 21550246, Score: 0.8011995553970337\n", + "\n", + "Query ID: 13\n", + "Query text: 5% of perinatal mortality is due to low birth weight.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 1263446, Score: 0.7953510284423828\n", + " Doc ID: 26611834, Score: 0.7630125880241394\n", + " Doc ID: 4791384, Score: 0.74913090467453\n", + "\n", + "Query ID: 36\n", + "Query text: A deficiency of vitamin B12 increases blood levels of homocysteine.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 16252863, Score: 0.8435379266738892\n", + " Doc ID: 18557974, Score: 0.8112655282020569\n", + " Doc ID: 3215494, Score: 0.8056871891021729\n", + "\n" + ] + } + ], + "source": [ + "print(\"Sample of retrieved results:\")\n", + "for query_id, doc_scores in list(vector_search_eval_results.items())[:5]: # First 5 queries\n", + " print(f\"Query ID: {query_id}\")\n", + " print(f\"Query text: {queries[query_id]}\")\n", + " print(\"Top 3 retrieved documents:\")\n", + " for doc_id, score in list(doc_scores.items())[:3]:\n", + " print(f\" Doc ID: {doc_id}, Score: {score}\")\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "nxQBuZEWimsy" + }, + "outputs": [], + "source": [ + "ndcg, _map, recall, precision = vector_search_retriever.evaluate(qrels, vector_search_eval_results, vector_search_retriever.k_values)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "FQjtEA49zoew", + "outputId": "6b9c9835-a0ea-4c58-974c-896f4b4b5f1b" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "NDCG:\n", + " NDCG@1: 0.5800\n", + " NDCG@3: 0.6430\n", + " NDCG@5: 0.6690\n", + " NDCG@10: 0.6920\n", + " NDCG@100: 0.7202\n", + " NDCG@1000: 0.7265\n", + "\n", + "MAP:\n", + " MAP@1: 0.5532\n", + " MAP@3: 0.6165\n", + " MAP@5: 0.6349\n", + " MAP@10: 0.6460\n", + " MAP@100: 0.6529\n", + " MAP@1000: 0.6532\n", + "\n", + "Recall:\n", + " Recall@1: 0.5532\n", + " Recall@3: 0.6885\n", + " Recall@5: 0.7530\n", + " Recall@10: 0.8198\n", + " Recall@100: 0.9450\n", + " Recall@1000: 0.9933\n", + "\n", + "Precision:\n", + " P@1: 0.5800\n", + " P@3: 0.2489\n", + " P@5: 0.1680\n", + " P@10: 0.0930\n", + " P@100: 0.0107\n", + " P@1000: 0.0011\n" + ] + } + ], + "source": [ + "vector_search_metric_dicts = [ndcg, _map, recall, precision]\n", + "\n", + "for name, metric_dict in zip(metric_names, vector_search_metric_dicts):\n", + " print(f\"\\n{name}:\")\n", + " for k, score in metric_dict.items():\n", + " print(f\" {k}: {score:.4f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ekUcNjn0xpRz" + }, + "source": [ + "# **Step 8: Custom Retrieval Class For Hybrid Search**\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "ZutxbNWXxrWt" + }, + "outputs": [], + "source": [ + "class MongoDBHybridSearch(BaseSearch):\n", + " def __init__(self, vector_store: MongoDBAtlasVectorSearch, search_index_name: str, batch_size=128):\n", + " self.vector_store = vector_store\n", + " self.search_index_name = search_index_name\n", + " self.batch_size = batch_size\n", + "\n", + " def search(self,\n", + " corpus: Dict[str, Dict[str, str]],\n", + " queries: Dict[str, str],\n", + " top_k: int,\n", + " score_function: str = \"dot\",\n", + " **kwargs) -> Dict[str, Dict[str, float]]:\n", + " results = {}\n", + " for query_id, query_text in queries.items():\n", + " hybrid_search = MongoDBAtlasHybridSearchRetriever(\n", + " vectorstore=self.vector_store,\n", + " search_index_name=self.search_index_name,\n", + " top_k=top_k\n", + " )\n", + " documents = hybrid_search.get_relevant_documents(query_text)\n", + "\n", + " # Convert to the format expected by BEIR\n", + " # Higher rank (lower index) gets a higher score\n", + " results[query_id] = {self._get_doc_id(doc): (len(documents) - i) / len(documents)\n", + " for i, doc in enumerate(documents)}\n", + "\n", + " return results\n", + "\n", + " def _get_doc_id(self, doc: Document) -> str:\n", + " # Attempt to get the document ID from metadata, fallback to content hash if not available\n", + " return str(doc.metadata.get('_id', hash(doc.page_content)))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "bWxs7qXPxree" + }, + "outputs": [], + "source": [ + "mongodb_hybrid_search = MongoDBHybridSearch(\n", + " vector_store=vector_store,\n", + " search_index_name=\"text_search_index\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "edM_DMC1xrgt" + }, + "outputs": [], + "source": [ + "hybrid_search_retriever = EvaluateRetrieval(mongodb_hybrid_search)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Clj7uIv-yL6B" + }, + "outputs": [], + "source": [ + "hybrid_search_results = hybrid_search_retriever.retrieve(corpus, queries)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_Jqjx3LWySFt", + "outputId": "a49b5943-d4f6-4d03-93fd-be95fb74e880" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sample of retrieved results:\n", + "Query ID: 1\n", + "Query text: 0-dimensional biomaterials show inductive properties.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 10906636, Score: 1.0\n", + " Doc ID: 43385013, Score: 0.999\n", + " Doc ID: 10931595, Score: 0.998\n", + "\n", + "Query ID: 3\n", + "Query text: 1,000 genomes project enables mapping of genetic sequence variation consisting of rare variants with larger penetrance effects than common variants.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 2739854, Score: 1.0\n", + " Doc ID: 23389795, Score: 0.999\n", + " Doc ID: 14717500, Score: 0.998\n", + "\n", + "Query ID: 5\n", + "Query text: 1/2000 in UK have abnormal PrP positivity.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 13734012, Score: 1.0\n", + " Doc ID: 18617259, Score: 0.999\n", + " Doc ID: 17333231, Score: 0.998\n", + "\n", + "Query ID: 13\n", + "Query text: 5% of perinatal mortality is due to low birth weight.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 1263446, Score: 1.0\n", + " Doc ID: 7662395, Score: 0.999\n", + " Doc ID: 30786800, Score: 0.998\n", + "\n", + "Query ID: 36\n", + "Query text: A deficiency of vitamin B12 increases blood levels of homocysteine.\n", + "Top 3 retrieved documents:\n", + " Doc ID: 16252863, Score: 1.0\n", + " Doc ID: 18557974, Score: 0.999\n", + " Doc ID: 33409100, Score: 0.998\n", + "\n" + ] + } + ], + "source": [ + "print(\"Sample of retrieved results:\")\n", + "for query_id, doc_scores in list(hybrid_search_results.items())[:5]:\n", + " print(f\"Query ID: {query_id}\")\n", + " print(f\"Query text: {queries[query_id]}\")\n", + " print(\"Top 3 retrieved documents:\")\n", + " for doc_id, score in list(doc_scores.items())[:3]:\n", + " print(f\" Doc ID: {doc_id}, Score: {score}\")\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "lGkJumGQyM7z" + }, + "outputs": [], + "source": [ + "ndcg, _map, recall, precision = hybrid_search_retriever.evaluate(qrels, hybrid_search_results, hybrid_search_retriever.k_values)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "V0yGPOLCybEb", + "outputId": "36c5eb5d-28fc-4e92-e3fb-da01dc1dbda3" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "NDCG:\n", + " NDCG@1: 0.5933\n", + " NDCG@3: 0.6739\n", + " NDCG@5: 0.6903\n", + " NDCG@10: 0.7128\n", + " NDCG@100: 0.7423\n", + " NDCG@1000: 0.7473\n", + "\n", + "MAP:\n", + " MAP@1: 0.5693\n", + " MAP@3: 0.6464\n", + " MAP@5: 0.6582\n", + " MAP@10: 0.6695\n", + " MAP@100: 0.6765\n", + " MAP@1000: 0.6767\n", + "\n", + "Recall:\n", + " Recall@1: 0.5693\n", + " Recall@3: 0.7262\n", + " Recall@5: 0.7657\n", + " Recall@10: 0.8297\n", + " Recall@100: 0.9600\n", + " Recall@1000: 0.9967\n", + "\n", + "Precision:\n", + " P@1: 0.5933\n", + " P@3: 0.2600\n", + " P@5: 0.1680\n", + " P@10: 0.0930\n", + " P@100: 0.0109\n", + " P@1000: 0.0011\n" + ] + } + ], + "source": [ + "hybrid_search_metric_dicts = [ndcg, _map, recall, precision]\n", + "\n", + "for name, metric_dict in zip(metric_names, hybrid_search_metric_dicts):\n", + " print(f\"\\n{name}:\")\n", + " for k, score in metric_dict.items():\n", + " print(f\" {k}: {score:.4f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "TZ4cS4Yg1DZJ" + }, + "source": [ + "# **Step 9: Evaluation Result Visualisation**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "cfA0nYdG1D3W" + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "\n", + "def plot_search_method_comparison(lexical_metrics, vector_metrics, hybrid_metrics, metric_names):\n", + " fig, axes = plt.subplots(2, 2, figsize=(20, 16))\n", + " fig.suptitle('Comparison of Search Methods', fontsize=16)\n", + "\n", + " search_methods = information_retrieval_search_methods\n", + " colors = ['#1f77b4', '#ff7f0e', '#2ca02c'] # Blue, Orange, Green\n", + "\n", + " for idx, (metric_name, ax) in enumerate(zip(metric_names, axes.flatten())):\n", + " lexical_data = lexical_metrics[idx]\n", + " vector_data = vector_metrics[idx]\n", + " hybrid_data = hybrid_metrics[idx]\n", + "\n", + " # Ensure all dictionaries have the same keys\n", + " all_keys = set(lexical_data.keys()) | set(vector_data.keys()) | set(hybrid_data.keys())\n", + "\n", + " x = np.arange(len(all_keys))\n", + " width = 0.25\n", + "\n", + " for i, (method, data) in enumerate(zip(search_methods, [lexical_data, vector_data, hybrid_data])):\n", + " values = [data.get(k, 0) for k in all_keys]\n", + " ax.bar(x + i*width, values, width, label=method, color=colors[i])\n", + "\n", + " ax.set_ylabel('Score')\n", + " ax.set_title(metric_name)\n", + " ax.set_xticks(x + width)\n", + " ax.set_xticklabels(all_keys, rotation=45, ha='right')\n", + " ax.legend()\n", + " ax.grid(True, axis='y', linestyle='--', alpha=0.7)\n", + "\n", + " plt.tight_layout()\n", + " plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "id": "9rd8peCB1WLB", + "outputId": "c8c78b46-ceaf-4019-883f-d1046c43d1aa" + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAB8YAAAYkCAYAAACY/GVtAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdeXxU5fn///eZmUw2IKwBTAIJoCyyyiZqBQUUrPhRxKKghKXYH0prixugVVErtm5US6UuCLZQERcqoiDmK1RFoIGwVRaRAMUQCCABkpBkZs7vj5hZMpOQQCYzDK8njzzaXHPOmfuec3nOnXPNfY5hmqYpAAAAAAAAAAAAAAAilCXUDQAAAAAAAAAAAAAAIJgojAMAAAAAAAAAAAAAIhqFcQAAAAAAAAAAAABARKMwDgAAAAAAAAAAAACIaBTGAQAAAAAAAAAAAAARjcI4AAAAAAAAAAAAACCiURgHAAAAAAAAAAAAAEQ0CuMAAAAAAAAAAAAAgIhGYRwAAAAAAAAAAAAAENEojAMAAACIOCtXrtS4ceN0ySWXqEGDBoqOjlbLli01ePBgvfTSS8rLywt1E88re/fulWEYSk1NDXVTwsKaNWt03XXXqXHjxrJYLDIMQ/PmzavWugcPHtTUqVPVvXt31a9fX3a7XRdddJF69OihiRMnat68eXI6ncHtQB174oknZBiGnnjiiVrbZnlOlv98+OGHVS7/85//3L3soEGDaq0dZzJgwAAZhqFVq1bV2XtWJTU1VYZhaO/evaFuCgAAAADUOVuoGwAAAAAAteXIkSO644479Pnnn0sqKwJdc801io+PV25urtasWaPPP/9cjz32mD7//HP17ds3xC3G+SYnJ0c///nPlZ+fr6uuukqpqamyWCxq167dGddds2aNfv7zn+v48eOqV6+e+vTpo+bNm+vUqVPaunWr3njjDb3xxhsaMWKE6tWrVwe9iRxz587VLbfcEvC1H374QStWrKj195w3b57GjRun9PT0an8xAgAAAAAQOhTGAQAAAESE8kLlzp071aFDB7322mv62c9+5rNMcXGx5s+fr8cff1wHDx4MUUvPP0lJSdq+fbuioqJC3ZSQ++yzz3T8+HGNGjVKCxYsqPZ6xcXF+sUvfuFe99VXX1WDBg18ltmxY4fmzp0rq9Va282OWFarVV26dNHy5cuVm5urFi1a+C0zf/58OZ1O9e7dW//5z39C0EoAAAAAQDjgVuoAAAAAIsKvf/1r7dy5U6mpqfr666/9iuKSFB0drbvvvlubNm1Sx44dQ9DK81NUVJQ6dOigtm3bhropIbd//35J0sUXX1yj9b766iv98MMPstlseu211/yK4pLUoUMH/elPf1JsbGyttPVCMX78eDkcDs2fPz/g62+99ZZiYmI0atSoOm4ZAAAAACCcUBgHAAAAcN7bs2ePFi5cKEl68cUX1bhx4yqXb968udq3b+8Xf+eddzRw4EA1btxY0dHRat26tcaPH69du3YF3I7383o//fRTDRgwQAkJCWrUqJFuvPFGbd261b3swoUL1a9fP9WvX18NGzbU8OHD9f333/ttc9WqVTIMQwMGDFBhYaGmT5+udu3aKSYmRhdddJEmTJigH374IWB7Pv/8c/36179W9+7d1bRpU0VHRys5OVkjR46sdKas9/Of9+/frwkTJiglJUVRUVEaO3aspKqfMf7dd99p/PjxSktLU3R0tOrVq6fWrVvr5z//ud56662A77lixQrdeOONSkxMdD9je+TIkcrMzAy4vPdzmjdt2qThw4e7+9epUye98MILMk0z4LpnUt19Pm/ePBmGoccff1ySNGPGDPczq6vz7PVDhw5JkurVq6f4+Pizaut7772nIUOGqFmzZrLb7UpKStKdd96pb7/9NuDywcoHSTJNUx988IFuvPFGtWjRQna7XS1atNBVV12lP/7xjyoqKgq4/by8PN17771KSUmR3W5XSkqKfv3rX+v48eNn9ZlI0ujRoxUdHR0w31avXq3du3frlltuUcOGDavczo8//qjHH3/c/fz3uLg4denSRU8//bQKCwt9lk1NTdW4ceMklc1I937e+YABAwJuv6a563A4NGfOHF1xxRVKSEhQTEyMLr74Yv3mN7+p9BggSd9++61uu+02NW3aVLGxsercubOef/75Kp9df/DgQd1333265JJLFBMTo7i4OKWkpGjgwIF6/vnnq/zcAAAAAOB8QWEcAAAAwHnv448/ltPpVMOGDXXTTTfVeH3TNJWenq477rhD//73v9WjRw8NHz5cMTExeuutt9SjRw8tX7680vX/9re/6ec//7kcDoeGDBmixMRELVu2TFdffbW+//57PfTQQ0pPT1dcXJyGDBmiBg0a6MMPP9TVV1+tH3/8MeA2S0pKNHDgQP35z39W+/bt3f2aO3euevXqpe+++85vnf/v//v/9Nprr8lisejKK6/UjTfeqISEBL377ru64oor9P7771fah++++049evTQJ598or59++qmm25S06ZNq/zctm3bpl69eumtt95SdHS0brzxRt1www1KSkrSv//9b/35z3/2W+f3v/+9hgwZok8++USXXHKJRowYoebNm+vdd9/V5Zdfrrlz51b6fitWrFDfvn21Y8cODR48WP369dOuXbv0wAMP6He/+12Vba2opvu8Xbt2Sk9PV7du3SRJ3bp1U3p6utLT0zVixIgzvl+rVq0kScePH6/x86gdDodGjhyp2267TatWrdIll1yim2++Wc2aNdOCBQvUq1evgPkZrHwoLS3ViBEjdOutt+rTTz9VWlqaRowYoa5du2rv3r2aOnWq+4sA3v73v//psssu0/vvv68+ffpo8ODBOnnypP7yl7/ouuuuU2lpaY0+l3KNGzfW//3f/2nnzp36+uuvfV578803JZXNKq/Kt99+q27duunJJ5/U4cOHddVVV2nQoEHKy8vT73//e1155ZXKz893Lz9ixAhdeeWVkqS2bdu6cyE9PV1Dhgzx235Nc7e4uFhDhw7VpEmTlJWVpSuvvFI333yziouL9corr6h79+7auHGj33pfffWV+vTpo/fee08JCQm6+eab1bJlS02fPl0jR44M2Pfc3Fz16tVLL7/8soqLizVkyBDddNNNSktL06ZNm/T0009X+dkBAAAAwHnDBAAAAIDz3F133WVKMq+99tqzWv/VV181JZlNmzY1s7Ky3HGXy2U+/vjjpiSzYcOG5uHDh33Wa926tSnJjI6ONj///HN33OFwmLfddpspyezcubPZpEkTc9OmTe7XCwoKzCuuuMKUZD799NM+2/ziiy9MSaYks127dua+ffvcrxUVFZm33nqrKcm8/PLL/frx4YcfmseOHQsYt9lsZpMmTczCwkKf18r7J8m88847zdOnT/utn52dbUoyW7du7RMfN25cwD6YpmkWFhaaq1ev9ol9+umnpiQzJibG/Oyzz3xee+ONN0xJZlRUlLlt2zaf1/r37+9u45w5c3xey8jIMA3DMK1Wq/m///3Prx2VOdt9Xv7a448/Xu33Mk3TdDqdZo8ePdz96N27t/nII4+YH3744RnbPX36dFOS2bdvX3PPnj0+ry1evNi0Wq1mo0aNzB9//NHntWDlw5QpU0xJZmpqqk9em2bZ5/f555+bx48fD7jNsWPH+mxz//79ZlJSkinJXLhwYZWfg7fynLRaraZpmuaKFStMSeb48ePdy+Tn55txcXFmamqq6XK5zLfeesuUZA4cONBnW4WFhWbbtm1NSeajjz5qFhcXu18rKCgw77jjDlOSOW7cOJ/1yreXnp5eaTvPNncffvhhU5LZtm1bMzs72x0vKSkxJ0yYYEoy09LSfNpaVFRkpqSkmJLM3/72t6bD4XC/tnnzZrNp06butnhvc8aMGaYk8+677zZdLpdPO0pKSnyObQAAAABwPqMwDgAAAOC8N2TIEFOSefvtt5/V+uVFsZdfftnvNZfLZXbt2tWUZP7hD3/wea28MP7ggw/6rbdx40Z3EWr27Nl+r7///vumJPOaa67xiXsXxpcsWeK33qFDh8y4uDhTkvn1119Xu4/lxb1ly5b5xMuLlo0bN/YpZnqrrDB+ww03mJLMjRs3VqsNAwcONCWZU6ZMCfj6jTfeaEoyJ06c6BMvLy4OHz484Hrl+//tt9+uVjtM8+z3+dkWxk3TNHNycsyhQ4e696/3zyWXXGI+++yzfoXqo0ePmrGxsWZMTIx54MCBgNu95557TEnmK6+8Uu22nG0+HDp0yLTb7aYkMzMzs1rvVb7N5ORks6CgwO/1Z5991q+ofSYVC+NOp9Ns1aqVWa9ePfPUqVOmaZrmnDlzTEnmE088YZqmWWlhvPxLEjfeeGPA9zp58qSZmJho2mw2ny8a1KQwXpPcLSoqMuvVq2dKMj/66CO/dQoKCszmzZubkswFCxa44//4xz9MSWZKSopZUlLit95LL70UsDBenj8ffPBBpf0AAAAAgEjArdQBAAAAXNAOHDjgftZ3enq63+uGYbifJfzFF18E3MYNN9zgF7v44our9XpOTk7AbVZ2W/jExET3rZpXrVrl93pOTo5ef/113X///frlL3+psWPHauzYsfrvf/8rSdq5c2fA9xs0aJASEhICvlaZPn36SJImTZqkFStW6PTp05Uu63A43Le59n5WtbcJEyZIqvxzHjZsWMB4x44dJanK5y57q419fjZatmypTz75RNu2bdMzzzyjYcOGKSkpSZK0a9cuTZ06Vf369fN53vYXX3yhoqIiXXnlle5lKyp/pvWaNWv8XqvtfPjiiy9UUlKinj17qmfPnjXpvgYOHKi4uDi/eE33XyAWi0Xp6ek6deqU3n33XUlljx2wWCyV5lu5ZcuWSVKltxqvV6+eevXqJYfDUemz2c+kJrmbmZmpU6dOqXHjxgHXi4uL0+233y7JNz/Ljwe/+MUvFBUV5bdeoFyXPP8dT506VR988IFOnTpVjR4BAAAAwPnHFuoGAAAAAMC5atasmSTp8OHDNV63vCDVpEkTNWjQIOAybdu29Vm2ovLnR3urV69ela/Xr19fkiotJqempsowjICvpaWlSSor8HqbMWOG/vCHP1T5rOYTJ05U+n419eCDD+qrr77S559/riFDhigqKkrdunXT1Vdfrdtvv129e/d2L3v06FF3X8vbX9HZfM6S3PutqsK8t9rY5+fi0ksv1aWXXur+ffv27frrX/+q2bNna/PmzXrkkUc0e/ZsSdKePXskSRkZGZXmQ7m8vDyf34ORD/v27ZMkdejQocq2BFJb+68y48aN09NPP625c+eqT58+Wr9+vQYNGqTWrVtXuV75Z3zXXXfprrvuqnLZip9xddWk7+U5V9l/J1Lg/Cw/HlS2XqNGjZSQkODzrHSprN8rV67UggULdOutt8pqtapTp0666qqrNGLECF177bVn6h4AAAAAnBcojAMAAAA47/Xs2VN///vftXHjRjmdTlmt1jp9f4ul6ptxnen1s2Wapvv/f/DBB3riiSdUr149/eUvf9G1116riy66SLGxsTIMQ9OnT9fMmTN91vEWGxtb4/ePi4vTypUr9Z///EfLly/XmjVrtGbNGmVmZurFF1/UPffc4y7w1oZgfY6h1rFjR73yyiuyWCx6+eWXtWTJEvfn5nK5JEnt2rXTlVdeWeV2vIvVociHMwn2/ktLS9OAAQP0xRdfaNq0aZKk8ePHn3G98s94yJAhat68eZXLnqnIXplwzl2LxaJ//OMfmj59upYtW6avv/5aX3/9tV599VW9+uqrGjZsmD788MM6P64CAAAAQG2jMA4AAADgvHfjjTdqypQpOn78uD766CPdcsst1V63/PbUR48e1YkTJwLOIC6fUVrZrayDYe/evWd8LTk52R0rv330H/7wB919991+63z33Xe12j5vvXv3ds8OdzgcWrJkicaMGaO//vWvGjFihK655ho1adJE0dHRKi4u1p49e9S1a1e/7dTV5xyu+/y6667Tyy+/rCNHjrhjKSkpkqT27dtr3rx51d5WsPKhfObzjh07zmr9YBs/fry++OILLV26VI0aNarWsSAlJUU7duzQhAkTNGLEiDpoZdXKcy47O7vSZQLlZ/n/r+zYcfz4cb/Z4t46deqkTp066cEHH5Rpmvp//+//adSoUVq6dKnefvtt9+MFAAAAAOB8Fb5fWQYAAACAamrbtq3uuOMOSdL999+vY8eOVbn84cOH3c9WTk5Odt+WOFDh0TRNd/yaa66pvUafwfHjx7V06VK/eF5enpYvXy7J82xpSe4+B5rRevjwYa1cuTI4Da3AZrNpxIgRuv766yVJmzZtcsevuuoqSYE/Z6nsmdBS8D/nUOzzymZme9u/f7+7feUGDhwou92uVatW1ehRAcHKh2uvvVZ2u10bNmzQxo0bz2obwXTrrbeqdevWatKkicaNG6eYmJgzrjN06FBJni8TVJfdbpdU9mWQ2tSrVy/Vq1dPx44d00cffeT3elFRkd555x1JvvnZv39/SWX9CHT7/LfffrvabTAMQwMHDtSoUaMkef47BgAAAIDzGYVxAAAAABHhlVdeUbt27ZSdna2rrrpKX331ld8yJSUlmjt3rnr06KHt27e74w888IAk6amnntLmzZvdcdM09fTTT2vTpk1q2LChJk6cGPyOeLn//vt9niNeXFyse++9VwUFBerTp4/PrbU7duwoSXrttddUUlLijufn5ys9Pb3KmaJn669//av7CwbecnNzlZmZKcm3MHv//fdLkl599VVlZGT4rDNv3jx99NFHioqK0n333Vfrba2orvf50qVLdfPNN2vlypVyOp1+r69atUpPPPGEJOn22293x5s3b65f//rXKigo0LBhw7R161a/dYuLi/XRRx/5zOIOVj4kJiZq0qRJkqTbbrtN27Zt83m9fKZxMPKtOmJjY7V3714dOXJEL7zwQrXWufvuu9W6dWstXrxYDz/8sE6ePOm3TG5url5//XWfWPkXGL799ttzb7iXmJgY3XvvvZLK/pspf667JJWWluq+++5Tbm6u0tLSfGa4jxgxQklJSdq/f7+mTZvmvkW8JG3btk1PP/10wPd7++23tWHDBr/4yZMntWrVKklnfwt5AAAAAAgn3EodAAAAQERo1KiRvv76a40cOVKrVq3Sz372M6Wlpalr166Ki4vToUOHtH79ep06dUoNGjTQRRdd5F73V7/6ldasWaO///3v6tWrl/r376/ExERt3LhRO3fuVGxsrBYuXKhmzZrVWX/69esnl8ul9u3b69prr1VcXJy++uor5eTkKDEx0W/2529/+1u9/fbb+uSTT9SmTRtdfvnlKi0t1erVqxUXF6fx48e7Z2TXltdee0333nuv0tLS1LlzZzVo0EB5eXn68ssvVVRUpGuvvVY33XSTe/mhQ4fq0Ucf1dNPP63BgwfryiuvVKtWrbRjxw5t3LhRVqtVc+bM0aWXXlqr7Qykrve5y+XSv/71L/3rX/9SQkKCLrvsMrVo0UIFBQXatWuXu6g9aNAgPfLIIz7rPvvsszp48KAWLlyo7t27q1u3bmrTpo1sNpsOHDigTZs2qaCgQJ9++qn7OePBzIc//elPys7O1kcffaRu3bqpb9++SktL05EjR/Tf//5XP/zwg7Kzs5WQkHBuH1odiY+P17Jly3TjjTfqT3/6k1577TV17dpVycnJKiws1K5du7R9+3YlJib6fFHi8ssv10UXXaSsrCxddtll6tKli6KiotS+fXs9+OCD59SmGTNmKDMzUxkZGerYsaOuueYa1a9fX998843279+vJk2aaPHixe5Z61LZlwIWLFigG264QS+88IKWLFmi3r176+jRo1q1apWGDRumDRs2+BTapbLn0aenp+uiiy5S9+7d1ahRI/3444/6+uuvlZ+fr86dO9f5l4IAAAAAIBiYMQ4AAAAgYiQmJuqLL77Qp59+qjFjxshqtSojI0Pvvfeevv32W/Xr10+zZs1Sdna2+vTp417PMAy9/fbbWrhwoa666ipt2LBB7733ngoLCzV27FhlZWW5b7dcV+x2uzIyMnTvvffqv//9r5YsWSKn06mxY8cqMzNT7du391k+LS1NWVlZGj16tKxWqz7++GNt3rxZd9xxh7KystzPqq5Nf/jDHzRp0iQ1bNhQa9eu1eLFi/Xtt9+qb9++mj9/vpYvXy6bzff72E899ZQ+/fRTDR06VNu3b9e7776rnJwc3XbbbVqzZo3Gjx9f6+0MpK73+ZAhQ7RixQo99NBD6ty5s/bs2aMPP/xQn332mQoLC3XzzTdr0aJF+uyzzxQXF+ezrs1m04IFC/TJJ5/o5ptv1uHDh/XRRx9pxYoVOnbsmIYNG6aFCxfq6quvdq8TzHyw2+1asmSJFi5cqEGDBmnXrl1avHixtmzZojZt2ui5555TixYtznr7oXDppZdqy5Yt+tOf/qSOHTtqy5YtWrx4sdatW6f4+Hg98MAD+vDDD33WsdvtWrFihW666SYdOHBA//jHP/Tmm29q2bJl59ye6OhoLV++XH/961/VrVs3ffnll/rwww8VFRWlX//619q8ebN69uzpt17//v21bt06DR8+XD/++KM+/PBDHThwQE8++aQWLVoU8L3uv/9+/fa3v1VycrI2btyoxYsXa+PGjerUqZNeeeUVrV27VvXr1z/nPgEAAABAqBlmdR50BgAAAACoE6tWrdI111yj/v37u29jDAAAAAAAgHPDjHEAAAAAAAAAAAAAQESjMA4AAAAAAAAAAAAAiGgUxgEAiBDz5s2TYRiKiYnRDz/84Pf6gAED1LlzZ/fvqampMgxDhmHIYrGoYcOG6tKli+6++26tW7eu0vc5ffq0XnrpJfXt21cJCQmKiYnRJZdcosmTJ2vXrl1+y2/ZskXjxo1TWlqaYmJiVK9ePXXv3l0PPfSQ9uzZUzudBwAAAAAgTJT/fW4Yhr766iu/103TVEpKigzD0I033uj3+vHjxxUTEyPDMLR9+/aA7zF27Fj3exiGoQYNGqhbt2564YUXVFxcXOt9AgAgEthC3QAAAFC7iouL9eyzz+qVV14547Ldu3fX/fffL0k6efKktm/frsWLF+v111/X7373O7344os+yx85ckRDhgzRhg0bdOONN2rUqFGqV6+edu7cqXfeeUevvfaaSkpK3Mu//vrrmjRpkpo2barRo0erQ4cOcjgc2rZtm95++23NmjVLRUVFslqttfshAMB5bMCAATJNM9TNAAAAwDmKiYnRwoULddVVV/nEV69erQMHDig6OjrgeosXL5ZhGGrRooUWLFigp59+OuBy0dHReuONNySVFdPff/99PfDAA/rPf/6jd955p3Y7AwBABKAwDgBAhOnevbtef/11TZs2TRdddFGVyyYlJenOO+/0if3xj3/UqFGj9NJLL+niiy/WpEmT3K+NHTtWWVlZeu+993Trrbf6rPfUU0/pkUcecf++Zs0aTZo0SVdeeaU+/vhj1a9f32f5F154QX/4wx/OtpsAAAAAAIS1G264QYsXL9bLL78sm81zKX7hwoXq2bOnjhw5EnC9f/zjH7rhhhvUunVrLVy4sNLCuM1m8/mb/p577lHfvn21aNEivfjii2e8JgAAwIWGW6kDABBhpk+fLqfTqWefffas1o+NjdXf//53NW7cWH/4wx/csxbXrVunZcuWacKECX5Fcansm+rPP/+8+/cZM2bIMAwtWLDArygulX1z/qmnnmK2OAAAAAAgIt1xxx06evSoVq5c6Y6VlJTovffe06hRowKus3//fn355Ze6/fbbdfvttys7O1tr1qyp1vtZLBYNGDBAkrR3795zbT4AABGHwjgAABEmLS1NY8aM0euvv66cnJyz2ka9evV0yy236IcfftC3334rSfroo48kSXfdddcZ1y8sLNT/+3//TwMGDFBycvJZtQEAAAAAgPNZamqq+vXrp3/+85/u2Keffqr8/HzdfvvtAdf55z//qfj4eN14443q06eP2rZtqwULFlT7Pb///ntJUpMmTc6t8QAARCAK4wAARKBHHnlEDodDf/zjH896G507d5bk+aN6+/btkqQuXbqccd3du3fL4XC4t+Ht2LFjOnLkiPvH+5nkAAAAAABEklGjRmnJkiUqKiqSJC1YsED9+/ev9DbnCxYs0P/93/8pNjZWkjRy5Ei9++67cjgcAZcv/9v6+++/18yZM7VkyRJ17dpV7du3D06HAAA4j1EYBwAgArVp00Z33XWXXnvtNR08ePCstlGvXj1J0smTJyVJJ06ckKSAt0WvqHzZ8m1UbFuzZs3cP+Uz0QEAAAAAiDS/+MUvVFRUpI8//lgnT57Uxx9/XOlt1Lds2aKtW7fqjjvucMfuuOMOHTlyRCtWrPBbvqCgwP23dbt27TR9+nT169dPH374YdD6AwDA+cwW6gYAAIDgePTRR/X3v/9dzz77rP785z/XeP1Tp05J8hTCGzRoIKmsUN6wYcMq1y1fp3wb3v71r3+ptLRUmzdv1gMPPFDjdgEAAAAAcL5o1qyZBg0apIULF6qwsFBOp1MjRowIuOw//vEPxcfHq02bNtq9e7ckKSYmRqmpqVqwYIF+/vOf+ywfExOjpUuXSpKio6OVlpbG48wAAKgChXEAACJUmzZtdOedd+q1117T1KlTa7z+tm3bJEnt2rWTJHXo0EGStHXrVv3sZz+rct127drJZrO5t+Gtf//+kiSbjWEIAAAAACDyjRo1ShMnTlRubq6GDh0a8Mvmpmnqn//8pwoKCtSpUye/1w8fPqxTp0753JnNarVq0KBBwWw6AAARhVupAwAQwR599NGzetb4qVOn9OGHHyolJUUdO3aUJA0bNkxS2TfYzyQ+Pl4DBgzQ6tWr9cMPP9S84QAAAAAARIhbbrlFFotFa9eurfQ26qtXr9aBAwf05JNPavHixT4/r732mgoLC7VkyZK6bTgAABGGqVoAAESwtm3b6s4779Tf/vY3tW7dulqztIuKinTXXXfp2LFjeuaZZ2QYhiSpX79+GjJkiN544w0NHTpUN998s896JSUlmj59up5//nlJ0mOPPaYBAwbozjvv1NKlS/2eN26aZu10EgAAAACAMFavXj29+uqr2rt3r/tL5xWV30b9wQcfVExMjN/rzz33nBYsWKA777wz2M0FACBiURgHACDCPfLII/r73/+unTt36tJLL/V57YcffnDPAD916pS+/fZbLV68WLm5ubr//vv1q1/9ymf5t99+W9ddd52GDx+uYcOGaeDAgYqPj9d3332nd955RwcPHnQXxn/2s5/pL3/5i37961/r4osv1ujRo9WhQweVlJRo165dWrBggex2u1q0aFE3HwQAAAAAACGSnp5e6WvFxcV6//33NXjw4IBFcUm66aab9Oc//1mHDx9WYmJisJoJAEBEozAOAECEa9eune68807Nnz/f77VNmzbprrvukmEYql+/vlJSUjRs2DD98pe/VJ8+ffyWb9asmdasWaO//vWvWrRokR555BGVlJSodevWuummm3Tffff5LD9p0iT169dPL730krvgHhUVpbZt2yo9PV2TJk1S27Ztg9Z3AAAAAADC3bJly3T8+PFKZ5NLZY83e+GFF/TOO+/oN7/5TR22DgCAyGGY3McUAAAAAAAAAAAAABDBLKFuAAAAAAAAAAAAAAAAwURhHAAAAAAAAAAAAAAQ0SiMAwAAAAAAAAAAAAAiGoVxAAAAAAAAAAAAAEBEozAOAAAAAAAAAAAAAIhotlA3oK65XC7l5OSofv36Mgwj1M0BAAAAAEQY0zR18uRJXXTRRbJYLuzvo/M3OAAAAAAgmGryN/gFVxjPyclRSkpKqJsBAAAAAIhw//vf/5ScnBzqZoQUf4MDAAAAAOpCdf4Gv+AK4/Xr15dU9uE0aNAgxK0BAAAAAESaEydOKCUlxf3354WMv8EBAAAAAMFUk7/BL7jCePmt2xo0aMAf5QAA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1atXT1LZM+qSk5O1ePFiffvtt3rsscc0ffp0vfvuu3XWZwAAAAAAAACIBFzfBQCg9nAr9Qj3l7/8RT169NAzzzzjjs2dO1cpKSnatWuXLrnkEj399NNauXKl7r77bm3btk3p6em66aabAm5v165devfdd7Vy5UoNGjRIktSmTRv361FRUZoxY4b797S0NH3zzTd699133YM1AAAAAAAAAMCZcX0XAIDaQ2E8wm3evFlffPGF+xt/3r7//ntdcsklstvtWrBggbp27arWrVvrpZdeqnR7mzZtktVqVf/+/StdZvbs2Zo7d67279+voqIilZSUqHv37rXRHQAAAAAAAAC4YHB9FwCA2kNhPMKdOnVKw4YN0x//+Ee/11q2bOn+/2vWrJEkHTt2TMeOHVN8fHzA7cXGxlb5fu+8844eeOABvfDCC+rXr5/q16+v5557TuvWrTuHXgAAAAAAAADAhYfruwAA1B4K4xHusssu0/vvv6/U1FTZbIF39/fff6/f/e53ev3117Vo0SKlp6fr888/l8Xi/wj6Ll26yOVyafXq1e5b7Xj7+uuvdcUVV+iee+7x2T4AAAAAAAAAoGa4vgsAQO3xPzPivJWfn69Nmzb5/Nx99906duyY7rjjDv3nP//R999/rxUrVmjcuHFyOp1yOp268847df3112vcuHF66623tGXLFr3wwgsB3yM1NVXp6ekaP368lixZouzsbK1atUrvvvuuJOniiy9WZmamVqxYoV27dun3v/+9/vOf/9TlxwAAAAAAAAAA5x2u7wIAEFzMGK+mvc/+PNRNOKNVq1apR48ePrEJEybo66+/1sMPP6zrrrtOxcXFat26tYYMGSKLxaKnnnpK+/bt08cffyyp7PY7r732mu644w5dd9116tatm9/7vPrqq5o+fbruueceHT16VK1atdL06dMlSb/61a+UlZWlkSNHyjAM3XHHHbrnnnv06aefBv8DAAAAAAAAAIAKzodruxLXdwEACDbDNE0z1I2oSydOnFBCQoLy8/PVoEEDn9dOnz6t7OxspaWlKSYmJkQtBPsBAAAAwPmsqr87LzR8FgCAusR1xfDAfgAA1KWa/N3JrdQBAAAAAAAAAAAAABGNwjgAAAAAAAAAAAAAIKJRGAcAAAAAAAAAAAAARDQK4wAAAAAAAAAAAACAiEZhHAAAAAAAAAAAAAAQ0WyhbgAAAAAAIHx1md8l1E3wsTV9a6ibAAAAgAgRbmNdifEuAAQThXEAAAAAAAAAAADgLIXblyz4ggUQGLdSBwAAAAAAAAAAAABENArjAAAAAAAAAAAAAICIxq3Uq+uJhDp+v/y6fT8AAAAAAAAAiERc2wUAAKIwHhGGDRum0tJSLV++3O+1L7/8UldffbU2b96srl27ntX2V61apWuuuUY//vijGjZseI6tBcJTuD0DRuI5MAAAAAAAAJGOa7sAANQdbqUeASZMmKCVK1fqwIEDfq+99dZb6tWr11kPnGqTaZpyOByhbgYAAAAAAAAAhAWu7QIAUHeYMR4BbrzxRjVr1kzz5s3To48+6o6fOnVKixcv1nPPPaevvvpK06ZNU2Zmppo2bapbbrlFM2fOVHx8vCSpuLhYjz32mBYuXKjDhw8rJSVF06ZN08CBA3XNNddIkho1aiRJSk9P17x581RcXKwHH3xQ77zzjk6cOKFevXrppZdeUu/evSV5vo34ySef6NFHH9XWrVv12WefacCAAXX7AQEAAAAAgHPGnbYAoPZxbRcAgLrDjPEIYLPZNGbMGM2bN0+mabrjixcvltPpVL9+/TRkyBDdeuut2rJlixYtWqSvvvpKkydPdi87ZswY/fOf/9TLL7+s7du3629/+5vq1aunlJQUvf/++5KknTt36uDBg/rzn/8sSXrooYf0/vvva/78+dq4caPatWun66+/XseOHfNp39SpU/Xss89q+/btYfHtRgAAAAAAAAAIB1zbBQCg7jBjPEKMHz9ezz33nFavXu3+1t5bb72lW2+9Va+88opGjx6t3/72t5Kkiy++WC+//LL69++vV199Vfv379e7776rlStXatCgQZKkNm3auLfduHFjSVJiYqL7OTQFBQV69dVXNW/ePA0dOlSS9Prrr2vlypV688039eCDD7rXf/LJJzV48OAgfwIAAAAAAAAAcP7h2i4AAHWDGeMRokOHDrriiis0d+5cSdLu3bv15ZdfasKECdq8ebPmzZunevXquX+uv/56uVwuZWdna9OmTbJarerfv3+13+/7779XaWmprrzySncsKipKffr00fbt232W7dWrV+10EgAAAAAAAAAiDNd2AQCoGxTGI8iECRP0/vvv6+TJk3rrrbfUtm1b9e/fX6dOndKvfvUrbdq0yf2zefNmfffdd2rb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AAAAAAAAkNRojAMAAAAAAAAAAAAAkhqNcQAAAAAAAAAAAABAUqMxDgAAAAAAAAAAAABIajTGAQAAAAAAAAAAAABJjcY4AAAAAAAAAAAAACCp0RgHAAAAAAAAAAAAACQ1GuMAAAAAAAAAAAAAgKRGYxwAAAAAAAAAAAAAkNRojAMAAAAAAAAAAAAAkhqNcQAAAAAAAAAAAABAUqMxDgAAAAAAAAAAAABIajTGAQAAAAAAAAAAAABJjcY4AAAAAAAAAAAAACCp0RgHAAAAAAAAAAAAACQ1GuMAAAAAAAAAAAAAgKRGYxwAAAAAAAAAAAAAkNRojAMAAAAAAAAAAAAAkhqNcQAAAAAAAAAAAABAUqMxDgAAAAAAAAAAAABIajTGAQAAAAAAAAAAAABJjcY4AAAAAAAAAAAAACCp0RgHAAAAAAAAAAAAACQ1GuMAAAAAAAAAAAAAgKRGYxwAAAAAAAAAAAAAkNRojAMAAAAAAAAAAAAAkhqNcQAAAAAAAAAAAABAUqMxDgAAAAAAAAAAAABIajTGAQAAAAAAAAAAAABJjcY4AAAAAAAAAAAAACCp0RgHAAAAAAAAAAAAACQ1GuMAAAAAAAAAAAAAgKRGYxwAAAAAAAAAAAAAkNRojAMAAAAAAAAAAAAAkhqNcQAAAAAAAAAAAABAUqMxDgAAAAAAAAAAAABIajTGAQAAAAAAAAAAAABJjcY4AAAAAAAAAAAAACCp0RgHAAAAAAAAAAAAACQ1GuMAAAAAAAAAAAAAgKRGYxwAAAAAAAAAAAAAkNRojAMAAAAAAAAAAAAAkhqNcQAAAAAAAAAAAABAUqMxDgAAAAAAAAAAAABIajTGAQAAAAAAAAAAAABJjcY4AAAAAAAAAAAAACCp0RgHAAAAAAAAAAAAACQ1GuMAAAAAAAAAAAAAgKRGYxwAAAAAAAAAAAAAkNRojAMAAAAAAAAAAAAAkhqNcQAAAAAAAAAAAABAUqMxDgAAAAAAAAAAAABIajTGAQAAAAAAAAAAAABJjcY4AAAAAAAAAAAAACCp0RgHAAAAAAAAAAAAACQ1GuMAAAAAAAAAAAAAgKRGYxwAAAAAAAAAAAAAkNRojAMAAAAAAAAAAAAAkhqNcQAAAAAAAAAAAABAUqMxDgAAAAAAAAAAAABIajTGAQAAAAAAAAAAAABJjcY4AAAAAAAAAAAAACCp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8ODBWrx4saZMmaLq6mrmScBZ4ujRo7ryyivVtm1bTZo0Sffff79ee+013XzzzVqyZIkCgQDNTJxQTU2NBg4cqAsvvDDUFP+///s//eY3v9G0adN04MABcoRmqa6uVq9evXThhRdq8+bNcrlc3G+jxUzTVHFxsS644AK9+eab2rdvn77//e9r9+7duvbaa7V3716yhWbx+XwaPny4zjvvPP3tb3/TvHnzNGTIEN1222168sknEz08nCFqa2t14403qqCgQIsWLdJPfvITTZ8+Xd26dVNdXZ0k3lY9GXAEcdICgYAefvhhtWvXTj/72c+0b98+3X777TTH0WKBQEA7duxQ37591bZtW0nSDTfcoIcffljDhg3T3XffrVWrVnFzjuOqq6tTz5491bVrV7300kuSpOnTp+v222/XjTfeqJKSEknihgrH5fP59B//8R/q16+f/vCHP+iaa67R6NGj1b17d5mmqX//+9/y+Xycj3BCPp9Phw8f1ujRo9W+fXv169dP48eP1+uvv67S0lJ9//vfT/QQcYb48ssvVV1dLb/fL6n+RV7Tp0/XsGHDtGLFCs2dO5dmGHCWWLNmjWprazVjxgyNHj1ad999tz766COlpqZqypQpeueddxI9RJwBXnrpJe3atUtXXHGF6urqdPfdd+unP/2pZs+ereeee059+/bV3//+d0m8GBRN8/l8+v73v6/c3FxdccUV+sY3vqEPP/yQ+220WG1trfbs2aObbrpJnTp1UuvWrXXPPffo0UcfVVZWlm666SYdPHiQRhRO6Msvv1RNTY3++7//Wz169NCNN96o6dOna/bs2frxj3+sX/7yl5K4tuH4SktL1aFDB02fPj10j/3hhx9q48aNuvbaa1VYWKh58+bp8OHDCR4pTgVXFJw0t9utc889VzfccIPuvfdeTZw4UQcPHtTtt9+uyspKmuNoNo/Ho7y8PJWXl0dcVL761a/qf/7nf1RQUKBf//rXqqmpSeAo4XRpaWnq0aOHDh48qH//+9+67bbb9MILL6hTp07Kzs7WX//6Vw0aNEgSr+xD03w+ny677DL953/+p1JSUiRJr732mlasWKHvfe97Gj16tPr06RP6+fXcUKEpgUBAFRUV2rp1a6hmWZauvPJKLVy4UK+88oqeeuqpBI4QThd8qNy1a1d5vV7t379fUv3PFk5NTdVDDz2k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Sb1791b//v0lRb6o0OPxaNGiRdq5c6cuuuiiRA0bMWBYvG8EmqGmpka//e1v9e6772rbtm1q27atqqqq9OCDD2rAgAGhC4x95eZtt92ml19+WX/96181YsQIbsyhQCCgG264QampqZo/f74++eQT/fvf/1ZJSYmuvfZavfLKK5Kk733ve1q9erV27typgoICrV69WnPnztV//Md/JHgP4BTHOyddeuml6t27d6OvmT9/vu6//369+uqr+trXvpaAUcNpmntts5s/f75KSkr00ksv6ZprrknAqOE0NTU1+sY3vqG1a9fq5ptv1rx589S2bVv5fL7QQ8PXX39dv/vd7/Tuu++qX79+at++vRYtWqQXX3xRo0aNSvAewAksy9KECRO0fft2vfTSS2rbtq0WL16sP/7xj3r77bf1xz/+UUOGDNF7772ncePGyev1KhAIyO/36xe/+IW+853vJHoXAMRQdXW1evfurf3792v9+vXq1atX6IXokrRt2zY9//zzeuaZZ1RUVKQBAwboyy+/1JQpU7Ro0aKozU6cfY4cOaJvf/vbSklJUZs2bTRkyBB98cUX+te//iXLsjRixAjdddddoe3Ly8v17rvv6v7779eLL76oW2+9NYGjh5M0p3FgP0d99tln+sY3vqGKigotXLhQ3/72t3kmCPl8Pl111VXq0qWLfv7zn2vTpk16++23NWvWLD366KOaMmWKDh06pFtvvVVffvmlqqurdckll+hvf/sb902IcPToUQ0aNEgXXnihRo4cqerqak2ZMkVdunTRzJkzdfXVV+u3v/2tFixYoIqKCn3rW9+Sz+fT//7v/2rhwoW6+eabE70LcIATzZNuuukmFRcXh7Z///339e677+q+++7TCy+8oG9/+9sJHD1OFY1xnNDhw4c1fPhwdevWTQMGDNDYsWO1Z88ebdq0SX/72990/vnn64477lCfPn0k1T/Y+9///V/dfffdeumll3TrrbeG3v6NSfDZ7ejRoxoyZIgmTpyo0aNHh+rvvvuubrnlFg0dOjT08zn+/e9/q7y8XB6PR7169dKgQYO4kYKk5p2Txo4dq69+9auSpA0bNmjBggV65pln9Pvf/54XWEBSy3NUXl6uhQsXavbs2XruuefIESTVPwD80Y9+pPfff19Dhw7VokWL1KFDB/3hD39o1Bzfvn27NmzYoJdeekn5+fkaPHiwrr32Wq5tkFT/lmwjRoxQnz599POf/zxU/+CDD/TUU0/pnXfe0Z/+9Cd97WtfU3V1tTZu3Ki6ujp17txZvXr1Yq4NJBGfz6fvfve7+vjjj5WRkaHy8nItW7ZMF110UUTj6dChQ1qxYoWmTJkiqX61+H333aeRI0dybYGqq6s1ePBgnX/++ZoxY4a6d++uxYsXa9CgQUpPT9drr72mF154QQ899JCuuOIKffnll5o1a5bmz5+vmTNn6pZbbiFHkNSyxkEwMzNnztSPfvSjiIUyEvOUs92BAwd03XXX6Ze//KWuuuoqSfVz4Oeff17/9V//pZ/97Gd64IEHdPjwYS1fvlzvvPOOOnbsqIEDB+qqq67inISQf/3rXyouLtbSpUt1/vnnS6q/7l177bWqra3Vb37zG33961/XqlWr9NZbb6m0tFR5eXkaNWqUbrjhBrKEFs+TKisrNXv2bP3xj3/UT3/6U918883k6ExnAcdRU1Njfe1rX7Nuvvlm69ChQ5ZlWdbf//5369lnn7Usy7I2bNhgjR071pozZ45lWZZlmqZlWZb1xBNPWK+88kqoFqzj7HbkyBGrW7du1qOPPhqqBbPx1ltvWZmZmdYTTzzR5NeTI7T0nFRdXW298sor1ujRo61FixZZlkWO0PIc1dTUWIsWLbLuuusua/HixZZlcW1D2PTp062ZM2datbW11oIFC6zLL7/cGjFihPXll19almVZXq+3ya8lR7C75557rOuuu86qqqqKqK9bt84aMWKEddttt1mVlZUJGh2A0+X999+3iouLrT/96U/Wzp07rREjRlgdO3a0PvjgA8uyLMvn80Vsf/ToUevo0aOh6w7XFvj9fusHP/iBddNNN1mHDx+2LMuyFi1aZF1zzTXWHXfcYW3dutWyLMv6z//8T2v+/Pmhr9u/f7+1efNmy7LIEeodOXLE6t+/vzVy5Ehr+/btlmVZ1muvvWYdOHDAOnz4sPWnP/3JGj58uPXuu++GvmbHjh3W9ddfby1YsMCyLLKEsIqKCislJcX661//allW5LOZX/7yl5bL5Qo9t4mGHCHorbfesrp162Z98sknlmXVP7OxLMuqqqqy+vfvbw0cODAiL/a5E+cknOw86fPPP7c++ugjy7LIUTJwJboxD2f77W9/q/bt2+v5559X+/btNXfuXE2dOlWPP/64XnjhBfXt21fDhw/XL3/5S9XW1so0TUnSww8/HHqFscSrQlH/yuFWrVppwoQJevnll1VaWiqpPhuWZWnw4MG69957tWzZMlVWVoayY0eO0JJzUk1NjTIzM3X99dfrmWee0Y033hg1Vzj7tDRHGRkZoVe2X3/99VzbEOH+++/XPffco/T0dI0aNUoTJkzQwYMHdfvtt6uyslIpKSny+/06cuRIo681DIMcIWTAgAHasWOH/va3v6muri5U79evn2688Ua9/fbbqqmpSeAIAZwOffr00V133aWRI0cqNzdXzzzzjC677DINHjxYH374oTweT+i+u7a2VmlpaUpLS1Pbtm0lcW1B/bsOfPzxx7rjjjvUunVrjRs3Tr/+9a9lGIY2bdqkxx9/XJ9++qlyc3O1cePG0Nd16tRJX/nKVySRI9S/M9KDDz6o7OxszZ8/X927d9drr72mmTNnqqSkRHv27NF3vvMd5ebmavv27aGvO//88zV37lyNHj2a+yZIUigHeXl5+s53vqOf//zn+uijj0LPAy3L0l133aWioiL95S9/UV1dXeg6Z0eOEHTxxRfL6/Xqueeek1T/rjler1dt2rTRkiVLtGXLFj311FOh7T0eT+j/ub7hZOdJ55xzji644AJJ5CgZ0BjHcQV/FmbHjh01duxY/e53v9N3vvMdDR48WLNmzdKCBQvUrVs3XXbZZcrIyAi9rVsQJwlI9TdUwRx885vfVLdu3TRnzhytXLlSUn1OPB6PzjvvPG3dupW3IkGTWnJOyszMlCSlpaWpXbt2kjgnod7J5Cg1NZUHzggJPqgxTVOWZSkjI0N+v18pKSkaPXq0JkyYoM8//1x33HFH6C23brjhBtXW1iZ45HCKo0ePaunSpSotLdWGDRskSXfddZf69++v++67T2+++WZEE/zqq69WWlqaDhw4kKghAzgNfD6fJOmKK65QamqqJCknJ0dz5swJNcc3bdokl8uluXPn6i9/+Yv8fr8kGgYIKy0tVXl5uYYNG6a33npLy5cv1+zZs/XWW2/pF7/4hb744gs98cQTeuONN0JvQQs01JLGwQcffCAp3ADt0qWLJO6bznZ+v19VVVXat29fqDZq1Cj5/X49/fTT2rlzZygjbdu2VXZ2tj744AOlpKTI5aJlgUjB84tpmurcubN+9rOf6bnnntOzzz4rqf6ZjdfrVceOHTV06FB99NFHiRwuHIx5EiQa4ziOAwcOaMuWLbrzzjtVV1enrVu36qc//an++7//WwsWLNDVV1+tSZMm6Z577uFBLxo5cuSIJk2apMrKSrnd7tADm8LCQk2cOFGffvqppk+frsWLF4e+pq6uTrm5uQoEAokaNhyMcxJigRwhFvbu3aujR4+qpqYm9LDP4/GEfvbr6NGj9YMf/EBffvmlLr30Ut1333268847lZGRkeCRwwkOHz6s/v376/7779ctt9yiW2+9Vffee68kacGCBRo4cKAmTJig3//+99qzZ48kaenSpZKkrKysRA0bwGmQkpIS8XnwhVjZ2dmh5viQIUP0wAMP6O6771bHjh0jVkEBkuR2u9W3b1+1adNG1dXV6ty5s7p16yZJ+sY3vqG8vDy9+eabMgxD48eP19atWxM8YjhRSxoH5513niReoIOwqqoq3XDDDbryyis1ePBg3X333dq3b59uuukm3XbbbfrnP/+pn/70pxHnn6ysLGVnZ6u2tpZ3+0NITU1N6EUUpmmGXjRx/fXX6/bbb9eMGTP0m9/8RpJCLyrMyMgI/T9ZQkPMkyDRGMdxWJalyspKHTlyRPv27dOmTZtUVVUV+v3vf//7atOmja6++mrNmzdP//jHPyLe9hFnr5qaGl111VWaPn26iouLVVVVJY/HE1oBcdNNN2nKlCkyDEN33nmnrr32Wv3Hf/x/9u48Pqaz///4ezJJJCRCLSkSYl9jjbUIlSaUVi2tpfbQlhslraVUUVVqV3rfpUWopRGq1lZRe0VprLclqLSqJGlVNlkn5/eHnyEV/VbvMDFezz7y0FxzzsznM3Ny5lznc851vaRRo0Zp2LBhKlKkiI0zQF7EPgm5ge0I/9SNGzc0e/ZsdezYUa1bt1ZAQICaNGmiFStWWDtKZrNZWVlZMpvN6tKli5588kldvHhR69atU9++femUQxaLRS+++KLKly+vnTt3as+ePRo1apQWLVqkjh07SpI2bNigtm3bavHixapRo4aefvppjRw5UtOmTbOeeAZgH9LS0vT1119rxIgR6t27t1544QUtX75cP/zwgyTJwcHBetHwreK4q6urZsyYobCwMLVt25bvFtylQIECunbtmtLS0lSsWDEdP35cERER1sdvTfmyefNmzZ8/XytWrLBhtMirKBzgn0pNTVWzZs1UsGBBjR49WiNGjNCWLVvUunVr7dy5U0OGDNHAgQN15swZBQQEaMiQIXrttdc0adIk9evXTwUKFOAiC0iSkpOTVaVKFVWqVElnzpzJdlzk5eWlQYMGqXPnznrrrbfUv39/LViwQB988IFWr16tDh06SOKCHdyN4yRIEpcW457y58+vcuXKycHBQaVLl9Yrr7yiGTNmqESJEmrQoIHee+89Va1aVdOmTdP27ds1ffp0ffPNN7YOGzZmsVg0duxYFSpUSO+//742btyoHj16aPny5SpYsKAyMjLk5OSkZ599VlWqVNGxY8cUHh6ucuXKacOGDXrmmWcYSh05Yp+E3MB2hH8iMTFRbdq0sQ6x/+9//1tXrlzR6dOntWHDBh0/flw9e/ZUjRo15ODgIMMwtGzZMq1Zs0bh4eF67rnnKFxA0s1hSRMTEzV48GAVLlxYhQsXVu3atVWlShV16NBBXbt21eeff64FCxbo0KFDOn78uBwdHTVlyhQ1bNiQYyTAjiQlJenFF1+Uk5OT3N3d1apVK/3xxx/64osvZBiGnn/+efXt21dms9n6tx8WFqaLFy9q/fr1fLdA0s0CVGRkpGJjYxUQEKD8+fOrZMmSysjI0M8//6wmTZrogw8+UFBQkLp27apTp04pLi5On3zyidzc3HT8+HH5+fnZOg3kQfcqHLRq1UrS7cLBiBEjNH/+fMXHx2vixIk2jhp5wQ8//KCUlBTNmDHDOgxxt27d9MwzzygkJETz58/Xq6++qlq1amn79u3asWOHfHx89MUXX1gv+OJ4FxkZGRo4cKC8vb1VqVIlNW/eXLt27VK1atWsI7VVqFBBo0aNUrNmzfTOO+8oMjJSrq6uWrVqlQIDA9mWwHES7onCOCTdvFL9+++/140bN9SsWTPlz59fbm5uqly5ssaPH6/w8HANHTpUGRkZatq0qSpXrqyrV6/qyJEjcnNzU0REhCpUqMAcMJDZbFbJkiVVunRpDRw4UGXKlNG8efPUo0cPffbZZ/Lw8LAWx8uVK6dy5cpZr+KTGOIGN7FPQm5gO0JuSElJUevWrVW8eHEtXLhQhQsX1rZt23ThwgW99tprqlGjhmbOnKn9+/erRo0a1s73lStXtHbtWnXo0MH63UanHBaLRRcvXsx2V5VhGGrWrJnCwsL0/PPPa/LkyRo7dqzq16+v+vXr2zBaAA9KcnKyWrRooTJlymjGjBkqW7asNm/erOeff16vvvqqNm3apGXLlqlixYpq2rSpTCaTfvrpJ+3YsUMrVqzIVhTnu+XxlZCQoNatW+vq1auKjo5WtWrVNHfuXLVq1UqNGjVSz5499dVXX2no0KEqU6aMfvjhB3l6emr06NFyc3PTrFmztHHjRr3zzju2TgU2RuEAuSk1NVVJSUnW76eUlBQVKFBAW7duVcuWLRUSEqKIiAg1atRIjRo10ujRo63TgnBOELecPXtWjo6OGjJkiJ566in961//kr+/v3bv3q1q1aopMzNTjo6OeuKJJ9SuXTs988wzkm5ufx4eHmxL4DgJf83AYy8hIcEICgoy2rdvb3Ts2NFITk62Pnb69GmjZ8+exscff2xkZGQYhmEY3377rbF7924jNTXVMAzDmDdvnuHs7GxERkbaJH7kTTdu3DAMwzDS09ONzz77zGjcuLHRrl074/r164ZhGEZGRoaRmJhoyxCRR7FPQm5gO0JumT17ttG2bVsjLi7OMAzDWLRokdG4cWOjZMmSxtKlSw3DMIxVq1YZlStXNm7cuGFkZmZmWz8rK8vIysp66HEj77m1HUyaNMmoUaOGsX379myPZWRkGGPGjDECAgKM69evs90AdiozM9P417/+ZTz//PPW/tDGjRuNp59+2ujZs6cRFRVlGIZhvPLKK9bvmVuuXr1qGAbfLTCM+Ph4o3Tp0ka3bt2MgwcPGnv27DEaNmxoVKlSxUhLSzNSUlKM1157zWjdurXx22+/3bX+e++9Z+TLl8/YsmWLDaJHXhIfH280btzYKFu2rGEymYzq1atbj1EGDhxoNGzY0Lh27ZphGIbx5ZdfGuPGjTNCQkKM2NhYwzAMY+bMmcYTTzxhXLhwwWY5IG+JiYkxihQpYowdO9balpaWZhiGYcTFxRkeHh7GlClTbBUeHiF79+61bjuXLl0y2rVrZxQtWtT473//axiGYVgsFsMwbp+DNgyD4yMYhsFxEv5vJsPg8pnHWWJiourVq6eGDRvq/fffV9GiReXq6qqTJ0/KYrGoVq1aWrZsmfbs2SN3d3eNHz9eBQsWlIODg06ePKnly5dr9uzZWrNmjZ577jlbpwMbysrKkoODg7KysmQymWQymaxX71ksFq1atUr//ve/VbRoUX322WcKDQ3VF198oa+//lqurq62Dh95BPsk5Aa2I+SmTp06qWrVqnrvvffUq1cvnT9/Xl27dlVERITOnDmjN998U6VKldKSJUsUGhpq63CRR90a7k+SDh8+rDFjxsjDw0MhISFq3LixdbkFCxbo/fff17Fjx1SoUCEbRQvgQUpNTVWHDh0UHByszp07q3fv3rp69aosFovi4+NVtWpVTZ48WUuXLlViYqI++OADhgJFNqmpqSpXrpzq1q2rTZs2Wdu3bt2qZ599Vtu3b1fLli0VExOjcePGadeuXWrRooU8PT11/PhxOTs76+DBg1q2bJlatGhhu0RgcwkJCfL19dVTTz2lYcOGKS0tTSNGjFB8fLyOHTumrKwsDR8+XNHR0Vq+fLmKFCmSbf3Jkydr0qRJWrdundq0aWOjLJAX3PqeunVucOHChXr77bc1ceJEDRw4UJKUnp4uZ2dnde7cWR4eHlq0aJGNo0ZedWuk0T+7fPmyXnvtNUVERGjPnj2qWrWqFi9eLLPZrJdfftk68gAebxwn4e9gb/EYS09PV7du3VStWjV9+umnypcvnyRp3bp1evnllxUYGKgpU6aoZ8+e8vHx0YIFC9SgQQPlz59fkuTi4iJXV1ft27ePYR6hq1ev6oknnlBmZqbc3NwkyVoUN5vN6tatm0wmkxYsWKC6devqp59+0ieffEJRHFbsk5Ab2I6Qm+Li4nT27Fl98MEHSktLU1RUlKZMmaKWLVtq6NCheuONNzR69GgVKFBANWvWtHW4yGOSkpL03nvv6a233pKHh4f1gkE/Pz8NHjxY77//vqZNm6b+/furbdu2km5OAeHt7S2LxWLj6AE8KDt27NDx48cVFBSk7du3a8+ePdq2bZsqVKigPXv2aPr06Xrvvfd08uRJde/eXRLDpSO7a9euyWQyKTk5WbGxsXriiSfk6OioYsWKqWDBgtY+tqenpxYuXKhNmzbp8uXLioqKUvny5dW2bVvNmjVL3t7eNs4EtpSamqoqVaqobt26WrlypbV94sSJevbZZ7V//361bNlSEyZM0Lhx49S4ceMcCwdff/01hYPH2I0bN/Tbb7+pdOnS1qK4JD377LM6c+aMZsyYIYvFosGDB8vZ2VmS5Orqav1/LvxCTv5cFL+1bZUqVUoff/yxXnvtNbVq1Uo9evTQjBkztHHjRorisOI4CX8He4zHWHR0tH766SdNnz7dekCyZcsWderUScOHD9emTZs0fvx4jRs3Ts2bN1fz5s0VGRmplJQU/fHHH6pbt67c3d3l7u5u40xgKzdu3NCCBQu0d+9enT9/XgULFlRCQoJGjRql+vXrq1KlSjKbzcrKypLZbFaXLl20fv167du3T+vXr7fOjcdBMCT2ScgdbEfITYZhKD4+XklJSYqJidHp06eVkJBgfXzgwIH6+uuv5e/vr5kzZ2rnzp1q0qSJ9YIMPL5u3LihFi1aKDIyUlFRUQoNDVXBggWtdz88//zzcnR01Keffqo+ffqodu3aKly4sDZu3KjPPvvsrjuyANgPs9msmjVryt3dXcnJySpevLhKlCghSWrevLnCw8O1ceNGeXl5acCAAYqKilKlSpVsHDXykpIlS2r//v165pln1KFDB23fvl1ms1l9+/bV008/rUaNGkm6XUho166djSNGXkThAP+r5ORkVa1aVbGxsTp69KiqVKlivTnGy8tLgwYNkpOTk9566y0dPXpU9evX1/Xr17V69Wpt3LhREhd+4aa0tDTt3LlTO3bsUGxsrOLj49W5c2dVrVpV9erVk4ODg3XbulUcb968uWbMmKGwsDC1bduW88uw4jgJfwdDqT/GwsPD1bVrV8XHx1vv8D1y5IhOnDihXr166eDBg+rVq5fKly+v2bNnq3LlyjaOGHlJYmKi2rRpoxIlSqh+/frq1auXrly5otOnT2vDhg0qU6aMevbsqRo1aki6WVxYsmSJ+vfvr/DwcHXq1Em3dj8cuEBin4TcwXaE3JSUlKS2bdtq3rx5qlmzpkaMGKGIiAjNnDlTDRo0UJ8+fZSUlKTQ0FDt3LlT06dP1zfffCMXFxdbhw4bslgsevPNN3XixAkFBARo48aNKlKkiJYvX56tOC5JP/74o44dO6bw8HCVK1dO/v7+euaZZzixA9ixvXv36s0339SePXv0ww8/qFWrVtq0aZNatWolSerWrZvKly+vESNGaNGiRYqPj9fEiRNtHDXygj9/N0RHRysgIECenp5KSUlRiRIltGHDBpnN5mxTeAD3Eh0drWeeeUbFixfX9u3b5eLiotq1a6tChQpau3atJGW7Cxi4JSMjQ8HBwbpw4YJcXV11/Phx7dq1S9WqVcu2/7l27Zq+++47vfPOO5Ju3i3+xhtvqGPHjhzvQtLNPveLL74oJycnRYas8QABAABJREFUubu7q1WrVvrjjz+0f/9+GYah559/Xn379pV0+3tw1qxZevPNN7PddCVxfvlxx3ES7gdHNo+xIkWKKF++fPr++++VlZUlSapTp4569eqlrKwsNWzYUMOHD9e5c+esQ8wCkpSSkqLWrVurWLFiWrhwoUaOHKkTJ07o4MGD6t69u8aMGaOrV69q//79km5/MV25ckVr166lKI4csU9CbmA7wj+VlpamvXv3auvWrbpx44Ykyc3NTZUrV9b48eOVmZmpoUOHql69emratKl8fX21efNmzZkzR25uboqIiFCFChU4cQiZzWaVLFlSbdu21bBhwzR48GD99ttv6tGjh+Lj4+Xk5KSMjAxJUrly5dShQwetXLlS7733nrUoDsA+pKam6rvvvtOXX36ppKQkZWVlqWTJksrIyNDPP/+sJk2a6IMPPlBQUJB69OihunXrat++fRo9erQ8PDx0/PhxFStWzNZpwMbS09MVFxeXre9ssVjk4+Oj7du3Kz09XUePHtWsWbOsJ3k52Yt7ufM4w8fHR9u2bVNMTIwCAgJUr149eXl5afXq1ZJubmcc2yInZ8+elaOjo4YMGaIlS5aoUaNG8vf316lTp2Q2m5WZmSlJeuKJJ9SuXTsdOHBABw4c0JYtW6xFcSA5OVktWrRQ/vz5NXfuXK1YsUKenp7q3bu3li1bpi5duig8PFz79u2TdPMc8k8//aQdO3ZoxYoVFMUhieMk/DMc3TxG0tPTderUKUVFRUmSKlasKCcnJ61atUrp6enZlr21I0lKSpKvry/FA2SzYMECFS5cWJ988okKFy6sxYsXa/z48Zo0aZKWLVummjVrqk2bNpo9e7ZSUlKsxamxY8eqQ4cOHLRAEvsk5A62I+SGxMREtW/fXjNnztTChQuzPRYSEiJ3d3ctWrRIJUqU0Jw5c7R161Z99NFH+uWXX+Tl5aX58+drxowZGjJkiHUIfzzeRowYoddee00uLi7q3LmzBg0adFdxPDMzU0lJSXetazKZOEYC7EBCQoKefvpp9ejRQx07dlSjRo20c+dOlS9fXo0aNVLPnj31xx9/aOjQoVq7dq3KlSunli1bKjIyUm5ubpo1a5Y2btyoZ5991tapwIZSUlJUs2ZNNWjQQGFhYTp69Kik2yd0fXx8FB4ergoVKqh///769ddfbRgt8jIKB8hNNWrUUL9+/dSxY0d5e3vr3//+d7biuKOjo/VcYEpKivLly6d8+fKpYMGCkjjexc39z6hRo1SqVCktXbpUZcuW1aZNmzRr1iyFhIToypUr6tq1q7y9vfXjjz9a1ytTpowWL16sbt26cX4ZHCfhH2Mo9cdEYmKiunXrptTUVFksFq1fv14FCxbU/Pnz9frrr+vNN9/UmDFj5OHhIenml9OSJUsUEhKisLAwtWnTxsYZIC/p1KmTqlatqvfee0+9evXS+fPn1bVrV0VEROjMmTN68803VapUKS1ZskShoaG2Dhd5EPsk5Aa2I+SGxMRE1atXTw0bNtT777+vokWLytXVVSdPnpTFYlGtWrW0bNky7dmzR+7u7ho/frwKFiwoBwcHnTx5UsuXL9fs2bO1Zs0aPffcc7ZOBzZ0a6jRrKws68m+zMxMOTo6ymKxaNWqVfr3v/+tokWL6rPPPlNoaKi++OILff3119Z5PAHYh4SEBPn6+uqpp57SsGHDlJaWphEjRig+Pl7Hjh1TVlaWhg8frujoaC1fvlxFihTJtv7kyZM1adIkrVu3juOVx9ylS5fUs2dPlStXTjExMYqPj1eNGjUUEhIib29v6/dHdHS0WrduLVdXV23evFklS5a0ceTIS1JSUlSnTh2lpaVp6tSpqly5smrXrp1tmejoaAUGBsrT01NhYWFsQ7inO6cFutPly5f12muvKSIiQnv27FHVqlW1ePFimc1mvfzyy3J0dLRBtMirUlNT1aFDBwUHB6tz587q3bu3rl69KovFovj4eFWtWlWTJ0/W0qVLlZiYqA8++IDh93EXjpPwT1EYfwzcOuHboEEDvfPOO/L09LQWCeLi4jRnzhxNnTpVgYGBCggIUL58+XTy5EmtWrVKCxcuVJcuXfjigVVcXJxatmypL7/8Ut7e3vL399eUKVPUsmVLSdIbb7yh8PBwFShQQDVr1lRYWJiNI0Zewz4JuYHtCLkhPT1dHTt2lKOjo8LCwpQvXz5J0rp16/Tyyy8rMDBQU6ZMUZUqVbR3714tWLBAhw4dso424OLiIldXV02bNk3169e3ZSrIA3799Vc98cQTyszMlJubm7X91vxlFotFn3/+uRYsWKDLly/rp59+0ieffGKdMw+AfUhNTVW5cuVUt25dbdq0ydq+detWPfvss9q+fbtatmypmJgYjRs3Trt27VKLFi3k6emp48ePy9nZWQcPHtSyZcvUokUL2yUCmzMMQ8nJyerbt6+aNWumQYMGaf/+/Ro5cqRKliwpwzA0efJkeXp6qmjRovrxxx/VqlUrrVy5Uo0bN7Z1+MhDKBzgQbpzHvpbxfEffvhBPXr00IwZM7Rx40a1bdvWxlEir9m8ebNeeeUVnTlzRgcPHtSAAQO0bds2VahQQXv27NH06dNVsmRJnTx5Ut27d9e//vUvW4eMPIbjJPwvKIzbuYyMDHXr1k1paWkKDw+Xi4uLpOwHLQkJCfr66681YcIEXbt2TU5OTmratKmCg4MVEBDAsCTIJjY2VvXq1dPGjRv1xBNPyNfXV8uWLVP79u0lSefPn1f79u3l7++vmTNnKiIiQk2aNLEWG/B4Y5+E3MB2hNwSFRWlTp06afr06QoKCpLJZNKWLVvUrl07DR8+XJs2bVKtWrU0btw4+fr6SpIiIyOVkpKiP/74Q3Xr1pW7u7vc3d1tnAls5caNG1qwYIH27t2r8+fPq2DBgkpISNCoUaNUv359VapUSdLt/VNmZqa6d++uNWvWaP369dZ58dgXAfbj119/tf79h4WF6YknnpCjo6MiIyPVqlUrffXVV2rUqJF1+U2bNuny5cuKioqSYRhq27atKlWqJG9vbxtmAVu6dUHVLbt371bXrl0VHh6upk2bSpLatWunLVu2qEyZMvLz81OzZs00dOhQpaamWo+NAYnCAf53aWlp2rlzp3bs2KHY2FjFx8erc+fOqlq1qurVqycp+37r8uXLat68uS5evKiwsDC9+OKLHO/iLl9//bXmzp2rr776SuvXr9f777+vb7/9VgUKFJAkDRkyRBs3bpSXl5e+/fZbRUdHW/tWeLxxnITcQGHczl2+fFlBQUGaMGGCOnfu/JfLJicnKy0tTWazWa6urnJ2dqZwgLskJSWpbdu2mjdvnmrWrKkRI0YoIiJCM2fOVIMGDdSnTx8lJSUpNDRUO3fu1PTp0/XNN9/wpQNJ7JOQO9iOkFvCw8PVtWtXxcfHW+/wPXLkiE6cOKFevXrp4MGD6tWrl8qXL6/Zs2ercuXKNo4YeUliYqLatGmjEiVKqH79+urVq5euXLmi06dPa8OGDSpTpox69uypGjVqSLp5YnrJkiXq37+/wsPD1alTJ/ZHgJ2Kjo7WM888o+LFi2v79u1ycXFR7dq1VaFCBa1du1ZS9gv6gFuSk5MVHBysNm3aqHfv3pJuXoQ1aNAgVa9eXSNGjNDUqVM1adIkbdu2TXFxcdq+fbs++ugjHTlyRLVq1bJxBsgrKBwgNyQlJenFF1+Uk5OT3N3d1apVK/3xxx/av3+/DMPQ888/bx396Fbxe9asWXrzzTezXQQqcbyL7Pbu3as333xTe/bs0Q8//KBWrVpp06ZNatWqlSSpW7duKl++vEaMGKFFixYpPj5eEydOtHHUsDWOk5BbmNzDzp09e1ZnzpyxHvTeq/N96tQpVatWzXpVFgctkG5eFfr999/rxo0batasmfLnzy83NzdVrlxZ48ePV3h4uIYOHaqMjAw1bdpUlStX1tWrV3XkyBG5ubkpIiJCFSpU4IQPrNgnITewHSG3FClSRPny5dP333+vFi1ayMHBQXXq1FGdOnWUlZWlhg0bavjw4Zo5c6Z1+HRAujlXZ+vWrVW8eHEtXLhQhQsX1rZt23ThwgW99tprqlGjhmbOnKn9+/erRo0a1hOFV65c0dq1a9WhQwf2SYCdufNuOB8fH23btk0BAQEKCAhQSkqKvLy8tHr1akl3F6wA6eY2NHLkSK1evVoJCQmSpN69eyt//vyqVauWFi5cqN9//13z5s3TZ599piZNmkiSnn/+eb399tvy9PS0ZfjIQ3IqHNSvX19BQUE6cOCAmjZtqqlTp2rnzp3at2+ftXAwbNgw+fv7UziApJvbUYsWLVSmTBnNmDFDZcuW1ebNm/X888/r1Vdf1aZNm7Rs2TJVrFhRTZs2lclk0k8//aQdO3ZoxYoVFMVhlZqaqsjISMXGxiogIED58+dXyZIllZGRoZ9//llNmjTRBx98oKCgIHXt2lWnTp1SXFycPvnkE7m5uen48ePy8/OzdRqwMY6TkJuoVtm5MmXKyNHR0Tq3WU6FgxUrVqhPnz5KTk62tnHAgsTERLVv314zZ87UwoULsz0WEhIid3d3LVq0SCVKlNCcOXO0detWffTRR/rll1/k5eWl+fPna8aMGRoyZIicnZ1tlAXyGvZJyA1sR/in0tPTderUKUVFRUmSKlasKCcnJ61atUrp6enZlr21vSQlJcnX15fCOLJZsGCBChcurE8++USFCxfW4sWLNX78eE2aNEnLli1TzZo11aZNG82ePVspKSnKysqSJI0dO5aiOGBn0tPTFRcXl+3v2WKxyMfHR9u3b1d6erqOHj2qWbNmWYvhFMWRE5PJZB0m1snJSWvWrNHSpUslScOHD5eHh4fmzp2rlStXqmPHjtnWu3Wyl0EhcWfhICwszLoN3SocLF68WKNHj9akSZOshYP27dvrww8/1JUrVyiKQ9LN77FRo0apVKlSWrp0qcqWLatNmzZp1qxZCgkJ0ZUrV9S1a1d5e3vrxx9/tK5XpkwZLV68WN26deN4F5JuTnP39NNPq0ePHurYsaMaNWqknTt3qnz58mrUqJF69uypP/74Q0OHDtXatWtVrlw5tWzZUpGRkXJzc9OsWbO0ceNGPfvss7ZOBTbGcRJyE4VxO+fs7Kxy5crp888/14kTJ6ztd+4E4uLiVLt2bTk6MoAAbkpMTFS9evVUrFgxzZs3T8uXL1f+/Pl18uRJHTt2TFWqVFFAQIAOHTqkESNG6Pr16/L391fz5s117tw5jR49Wm+88YbWrFmjOnXq2Dod5CHsk5Ab2I7wTyQmJqpjx44aOnSoXn31VSUkJMjb21uTJ0+2FjXj4+Oty2dlZenTTz/Vu+++qwEDBqhIkSI2jB55zd69e1W7dm0VLVpUvXr10qeffqquXbvK399fc+bM0cqVK1WiRAk1atRIrq6udxXBTCYTJwkBO5CSkqKaNWuqQYMGCgsL09GjRyXdLnz7+PgoPDxcFSpUUP/+/fXrr7/aMFrkZRaLRZL0+uuv68UXX9STTz4pJycnLVmyRJ999pkkWef0ffrppyXlfHKX7xZQOEBuyMjI0IULF9SzZ0+5ubmpd+/emjdvnkwmk06fPq1Jkybp0qVL8vb21n//+19Jt7ebW9sRx7tISEiQr6+vfHx89Pnnn2v37t1yc3PT4MGDlZ6erlmzZqlOnTrq3r27fv/9d7Vv317vvvuuZs6cqWLFimny5MkaM2aMli9frnLlytk6HdgQx0nIbcwxbkcsFosSExN19OhRFStWTKVLl5a7u7vWr1+vDh06qHPnzho5cqR16JH09HQtXbpU48aN07JlyxQYGGjjDJAXpKenq2PHjnJ0dFRYWJjy5csnSVq3bp1efvllBQYGasqUKapSpYr27t2rBQsW6NChQ9Y76VxcXOTq6qpp06apfv36tkwFNsY+CbmB7Qi54dYFXw0aNNA777wjT09PeXh4SLp5EcWcOXM0depUBQYGKiAgQPny5dPJkye1atUqLVy4UF26dMk2RC4eb3FxcWrZsqW+/PJLeXt7y9/fX1OmTFHLli0lSW+88YbCw8NVoEAB1axZU2FhYTaOGMCDcunSJfXs2VPlypVTTEyM4uPjVaNGDYWEhMjb21uurq6Sbs453rp1a7m6umrz5s0qWbKkjSNHXnHnlECZmZkyDEPjx49XamqqQkJC9PrrrysuLk4hISEKCgqyXmTBPKvIyZ3TNHTp0kWFChVSXFycrl27puDgYPXs2VMzZszQypUrtXv3brm7u3OMixxt3rxZr7zyis6cOaODBw9qwIAB2rZtmypUqKA9e/Zo+vTpKlmypE6ePKnu3bvrX//6l61DRh6TmpqqcuXKqW7dutbR/iRp69atevbZZ7V9+3a1bNlSMTExGjdunHbt2qUWLVrI09NTx48fl7Ozsw4ePKhly5apRYsWtksENsVxEh4UbqOyE0lJSRo+fLiOHz+uQ4cOyc3NTSVLltTixYvVvn17LVmyRP369dOpU6cUEBCgQoUK6dKlS1qzZo0++eQTCgewio6O1k8//aTp06dbh0DfsmWLOnXqpOHDh2vTpk0aP368xo0bp+bNm6t58+aKjIxUSkqK/vjjD9WtW1fu7u5yd3e3cSawJfZJyA1sR8gNGRkZ6tu3rypXrqxPP/1ULi4ukm53sIoVK6ZRo0apVq1amjBhgqZPny4nJyc1bdpUa9euVUBAAHfNIBvDMBQfH6+kpCTFxMTo9OnT1jnOJGngwIH6+uuv5e/vr5kzZ2rnzp1q0qSJ9WJDAPbBMAwVLlxYxYoVU+3atTVo0CDt379fI0eO1KhRo2QYhiZPnixPT0/5+Phoy5YtatWqlX766ScK45B081h34MCBKlWqlN5++205ODgof/786tu3r/z8/BQYGKg5c+Zo2LBhmjlzpgzDUL9+/fTNN99oyJAhKlq0qK1TQB5x67jWbDZbCwfly5dXamqqxo0bp9dff12ffPKJ3N3d9a9//UuzZ8/WjBkzNHHiRIriyJHZbFbNmjXl7u6u5ORkFS9eXCVKlJAkNW/eXOHh4dq4caO8vLw0YMAARUVFWUcqACTp2rVrMplMSk5OVmxsrJ544gk5OjqqWLFiKliwoPXiQU9PTy1cuFCbNm3S5cuXFRUVpfLly6tt27aaNWuWvL29bZwJbIXjJDxI3DFuBxISEtS4cWNVq1ZNzz33nJo1a6Zt27Zp6dKlOnnypEJDQ9WhQwft2LFDCxYsUGRkpBwdHeXv76+uXbuqZcuWXCEKq/DwcHXt2lXx8fFyc3OTJB05ckQnTpxQr169dPDgQfXq1Uvly5fX7NmzVblyZRtHjLyGfRJyA9sRcsvly5cVFBSkCRMmqHPnzn+5bHJystLS0mQ2m+Xq6ipnZ2fmxsNdkpKS1LZtW82bN081a9bUiBEjFBERoZkzZ6pBgwbq06ePkpKSFBoaqp07d2r69On65ptvrBdlAHi03XlHpiTt3r1bXbt2VXh4uJo2bSpJateunbZs2aIyZcrIz89PzZo109ChQ5Wamsq+AJJuXljRv39/LVmyRJIUGBioypUrq1OnTmrevLmmTZummJgYzZw5UydOnNCkSZMUGxursmXLasCAAWrSpImNM0Beca/Cwblz5+Tn56ewsDBVr15dw4YNU2xsrEJCQhQZGant27dr48aNFA6Qo7179+rNN9/Unj179MMPP6hVq1batGmTWrVqJUnq1q2bypcvrxEjRmjRokWKj4/nDk3cJTo6Ws8884yKFy+u7du3y8XFRbVr11aFChW0du1aSdnvCAZu4TgJDxqF8UdcQkKCatasqfr162vZsmVydnaW2WyWxWJRdHS0hg0bpr179+rAgQOqWrWq0tLS5OTkJCn7XC8UD3DLt99+q3bt2mnTpk1q0aJFtoOTWwcrH3/8sWbOnKlvv/2WK/eQDfsk5Aa2I+Smb7/9VoGBgfrll1/05JNP3rPjferUKVWrVs36O9sPJCktLU3ff/+9bty4oWbNmlmnjnnllVcUFxen8PBwXblyRTNnztS///1vVa5cWVevXtWRI0fk5eWlsWPH6sqVK/r444+tI/EAeHQlJycrODhYbdq0Ue/evSVJN27c0KBBg1S9enWNGDFCU6dO1aRJk7Rt2zbFxcVp+/bt+uijj3TkyBHVqlXLxhkgLzl79qxGjRolk8mkIkWKyMfHR5MnT1ZISIhOnTql8+fPa8OGDSpbtqxOnDiht99+WxMmTFCdOnVsHTryCAoHyA2pqamKjIxUbGysAgIClD9/fl28eFEvvviiwsLCVLFiRX344YcKCQlR165dderUKcXFxen06dNyc3NTnz595Ofnp8GDB9s6FeQBf+5HR0dHKyAgQJ6enkpJSVGJEiW0YcMG6zmeOy82BO7EcRIeJC7HeYSlp6erYcOGevLJJxUeHi5XV1eZzWZlZWXJbDarfPnyev/9961DhFosFjk6OsrBwUEODg7ZhgXlxO/jKz09XadOnVJUVJQkqWLFinJyctKqVauUnp6ebdlb20lSUpJ8fX2tJ4cBiX0ScgfbEXJbmTJl5OjoaJ3XLKei+IoVK9SnTx8lJydb29h+kJiYqPbt22vmzJlauHBhtsdCQkLk7u6uRYsWqUSJEpozZ462bt2qjz76SL/88ou8vLw0f/58zZgxQ0OGDKEoDtgBwzA0cuRIrV69WmFhYVq6dKkkKX/+/KpVq5YWL16s0aNHa9KkSfrss8/UpEkTtW/fXh9++KGuXLlCURx3qVy5sj744ANJN0e4eeGFF/Tdd9/JZDIpNjZW//3vf/Xdd9/JMAz5+vpqxYoVnOxFNiaTSSNHjtTzzz+v9u3by8vLS8WKFVNQUJDGjh2rAwcO6JtvvtHFixfl6+urcePGycPDQ0OHDqUoDkk3L0p/+umn1aNHD3Xs2FGNGjXSzp07Vb58eTVq1Eg9e/bUH3/8oaFDh2rt2rUqV66cWrZsqcjISLm5uWnWrFnauHGjnn32WVunAhtLT09XXFxctn60xWKRj4+Ptm/frvT0dB09elSzZs2yFsMpiuOvcJyEB4nC+CPMZDKpevXqOnPmjA4ePCjp7uFHfH199fTTT+vSpUsymUzZvnAYpgSJiYnq2LGjhg4dqldffVUJCQny9vbW5MmTtXjxYo0fP17x8fHW5bOysvTpp5/q3Xff1YABA1SkSBEbRo+8hn0ScgPbEXKbs7OzypUrp88//1wnTpywtt95EUVcXJxq164tR0dHW4SIPCgxMVH16tVTsWLFNG/ePC1fvlz58+fXyZMndezYMVWpUkUBAQE6dOiQRowYoevXr8vf31/NmzfXuXPnNHr0aL3xxhtas2YNnXPATphMJuv8qU5OTlqzZo21OD58+HB5eHho7ty5WrlypTp27JhtPU9PT0nZv3sA6fZJX8Mw9MYbb8jBwUHvvfeetmzZojVr1ujll1+2FhluTXUG3InCAf6phIQE+fr6ysfHR59//rl2794tNzc3DR48WOnp6Zo1a5bq1Kmj7t276/fff1f79u317rvvaubMmSpWrJgmT56sMWPGaPny5SpXrpyt04ENpaSkqGbNmmrQoIHCwsJ09OhRSbcL3z4+PgoPD1eFChXUv39//frrrzaMFo8SjpPwoDCU+iMoJSVFwcHBWrFihQzDUPfu3bVp0yZt3bpVTz31lHXIklv/jh07VuvXr9fRo0c54QurWyd8GzRooHfeeUeenp7y8PCQdLNAMGfOHE2dOlWBgYEKCAhQvnz5dPLkSa1atUoLFy5Uly5dGGYWktgnIXewHSE3WCwWJSYm6ujRoypWrJhKly4td3d3rV+/Xh06dFDnzp01cuRI+fn5Sbp5VfvSpUs1btw4LVu2TIGBgTbOAHlBenq6OnbsKEdHR4WFhSlfvnySpHXr1unll19WYGCgpkyZoipVqmjv3r1asGCBDh06ZB1Jx8XFRa6urpo2bZrq169vy1QA5JI7h/rs0qWLChUqpLi4OF27dk3BwcHq2bOnZsyYoZUrV2r37t1yd3enr4T7cu7cOQ0ZMkSSNHr0aLVo0cL6GNsS/o6oqCgNHTpUhmFo2rRpqlWrluLj47Vjx45sF+sA0s3h08uVK6e6detaR9aSpK1bt+rZZ5/V9u3b1bJlS8XExGjcuHHatWuXWrRoIU9PTx0/flzOzs46ePCgli1blm1/hcfTpUuX1LNnT5UrV04xMTGKj49XjRo1FBISIm9vb7m6ukq6Oax669at5erqqs2bN6tkyZI2jhyPCo6TkNsojD+CTpw4IX9/f1WsWFERERHZCgjffPONmjRpYr27LjExUQMHDpS3t7emTJnCjgKSpIyMDHXr1k1paWkKDw+Xi4uLpOx3ZSYkJOjrr7/WhAkTdO3aNTk5Oalp06YKDg5WQECA9W4HtiewT0JuYDvC/yopKUnDhw/X8ePHdejQIbm5ualkyZJavHixmjRpoqVLl6pfv36qWrWqAgICVKhQIV26dElr1qzRJ598opdeesnWKSCPiIqKUqdOnTR9+nQFBQXJZDJpy5YtateunYYPH65NmzapVq1aGjdunHx9fSVJkZGRSklJ0R9//KG6devK3d1d7u7uNs4EwP/qzv5RZmamDMPQ+PHjlZqaqpCQEL3++uuKi4tTSEiIgoKCrHdCTZw40caR41F07tw5DR06VGazWSNGjJC/v7+tQ8IjhsIB/q5ff/1V9evXV6VKlRQWFqYnnnhCjo6OioyMVKtWrfTVV1+pUaNG1uU3bdqky5cvKyoqSoZhqG3btqpUqZK8vb1tmAXyAsMwlJycrL59+6pZs2YaNGiQ9u/fr5EjR6pkyZIyDEOTJ0+Wp6enihYtqh9//FGtWrXSypUr1bhxY1uHj0cIx0nITRTGH0FZWVk6dOiQevfuLTc3Nx06dCjHu+skadGiRXrvvff4skE2ly9fVlBQkCZMmKDOnTv/5bLJyclKS0uT2WyWq6urnJ2dKYojG/ZJyA1sR/hfJCQkqHHjxqpWrZqee+45NWvWTNu2bdPSpUt18uRJhYaGqkOHDtqxY4cWLFigyMhIOTo6yt/fX127dlXLli05WQir8PBwde3aVfHx8dbh2I4cOaITJ06oV69eOnjwoHr16qXy5ctr9uzZqly5so0jBvAgJCUlaeDAgSpVqpTefvttOTg4KH/+/Dp37pz8/PwUFham6tWra9iwYYqNjVVISIgiIyO1fft2bdy4UUWLFrV1CngEnTt3Tv3795ezs7NWr16twoUL2zokPGIoHODvio6O1jPPPKPixYtr+/btcnFxUe3atVWhQgWtXbtW0t3TmgG33DmajiTt3r1bXbt2VXh4uJo2bSpJateunbZs2aIyZcrIz89PzZo109ChQ5Wammq9SQu4HxwnIbdQGH9E/PlkrcVi0ffff6/evXurYMGCdxUQIiIidPHiRXXs2FGrVq36P4ufeLx8++23CgwM1C+//KInn3zynge6p06dUrVq1ay/UzTALeyTkBvYjpAbEhISVLNmTdWvX1/Lli2Ts7OzzGazLBaLoqOjNWzYMO3du1cHDhxQ1apVlZaWJicnJ0k3L/C6tQ3yHYdbvv32W7Vr106bNm1SixYtsh0j3Tpm+vjjjzVz5kx9++233CkD2CHDMNS/f38tWbJEkhQYGKjKlSurU6dOat68uaZNm6aYmBjNnDlTJ06c0KRJkxQbG6uyZctqwIABatKkiY0zwKMsKipK8fHxTMeBf4zCAe7lz32e6OhoBQQEyNPTUykpKSpRooQ2bNhg7U/dWfgEbklOTlZwcLDatGmj3r17S5Ju3LihQYMGqXr16hoxYoSmTp2qSZMmadu2bYqLi9P27dv10Ucf6ciRI6pVq5aNM8CjjOMk5AYK44+A5ORkjR8/Xp6ennr55Zfl5OSkYsWKSZIOHz6sbt26yc3NTZGRkTIMQz169NDnn38uSVq+fLm6d+/OyV5kc+HCBVWvXl3z589X//79c1xmxYoVmjt3rnbu3KkCBQo85AiRl7FPQm5gO0JuSE9PV61ateTh4aGIiAhr+50XfJ04cUIdO3ZU1apVtW7dOkmynuDhDghIN7ej8+fPy9HRUZUqVdKlS5dUo0YNvfTSS5o3b162uxlu7XdmzJih7777Tp988omKFCliw+gBPChnz57VqFGjZDKZVKRIEfn4+Gjy5MkKCQnRqVOndP78eW3YsEFly5bViRMn9Pbbb2vChAmqU6eOrUMHAAoHyCY9PV3x8fHWPrd0+47f6Ohovfjii/rhhx90+vRpRkPCXzIMQ4MHD9Z//vMftW7dWl26dLEWx2fPnq2FCxeqffv2mjdvnj777DN17NjRul5sbKw8PT1tGT4ASKIwnucZhqHg4GCFhoZKkurUqaPU1FT17NlTvr6+atu2rQ4cOKDhw4crMzNThw8fVnp6ul5//XW1adNGzz//PMNe4y6XLl1SUFCQSpYsqdmzZ1vnx7yzyDRnzhydOnVK8+bNU758+WwZLvIQ9knIDWxHyC0ZGRnq1q2btm/frq1bt6phw4Y5FrtfffVVff/99/rhhx8ohCObxMREdevWTampqbJYLFq/fr0KFiyo+fPn6/XXX9ebb76pMWPGyMPDQ9LNE4hLlixRSEiIwsLC1KZNGxtnAOBBOnv2rEaPHq3U1FRNnz5dGRkZWrt2rXbu3KkDBw7os88+U/fu3WUymZSUlGSdfgEAgLwiJSVFderUUVpamqZOnarKlSurdu3a2ZaJjo5WYGCgPD09FRYWppIlS9omWDwS5s6dq+HDh+u5555TVlaWOnfubC2ON2rUSMeOHdPnn3+u9u3b57g+NzkAsDUK44+AqKgohYSESJJq164tLy8vLVmyROfPn1eFChXk7e0tX19fvf/++6pfv7727dtnPSlM4QAWi0WJiYk6evSoihUrptKlS8vd3V3r169Xhw4d1LlzZ40cOVJ+fn6Sbl5FunTpUo0bN07Lli1TYGCgjTNAXsM+CbmB7Qj/i5SUFAUHB2vFihU5zkV/q6N969+xY8dq/fr1Onr0qBwdHW0dPvKIxMRE1atXTw0aNNA777wjT09PawE8Li5Oc+bM0dSpUxUYGKiAgADly5dPJ0+e1KpVq7Rw4UJ16dKFkzrAYyAqKkpDhw6VYRiaNm2aatWqpfj4eO3YscN6FxQAAHnVpUuX1LNnT5UrV04xMTGKj49XjRo1FBISIm9vb7m6ukq6WRxv3bq1XF1dtXnzZorjuMudw+t36dJFhQoVUlxcnK5du6bg4GD17NlTM2bM0MqVK7V79265u7vTXwKQJ1EYf0ScPXtWI0eOVGpqqubPn6+KFSvq0qVLWrFihY4fP669e/fq8uXLkqSIiAg1aNDAxhEjL0hKStLw4cN1/PhxHTp0SG5ubipZsqQWL16sJk2aaOnSperXr5+qVq2qgIAAFSpUSJcuXdKaNWv0ySef6KWXXrJ1Csij2CchN7Ad4Z86ceKE/P39VbFiRUVERGQrjn/zzTdq0qSJ9UKKxMREDRw4UN7e3poyZQodc0i6PdpAWlqawsPDrcOl3zniQEJCgr7++mtNmDBB165dk5OTk5o2barg4GAFBARwkQ7wGDl37pyGDBkiSRo9erRatGhhfYzvFQBAXmUYhpKTk9W3b181a9ZMgwYN0v79+zVy5EiVLFlShmFo8uTJ8vT0VNGiRfXjjz+qVatWWrlypRo3bmzr8JFH3NlHyszMlGEYGj9+vFJTUxUSEqLXX39dcXFxCgkJUVBQkCpUqKD+/ftr4sSJNo4cAHJGYfwREhUVZe2MjxkzRv7+/tbHzp49q5iYGBmGka0dj6+EhAQ1btxY1apV03PPPadmzZpp27ZtWrp0qU6ePKnQ0FB16NBBO3bs0IIFCxQZGSlHR0f5+/ura9euatmyJSd58JfYJyE3sB3hn8jKytKhQ4fUu3dvubm56dChQzneOS5JixYt0nvvvcfJHWRz+fJlBQUFacKECercufNfLpucnKy0tDSZzWa5urrK2dmZojjwGDp37pyGDh0qs9msESNGcGwCAMiz7ryzV5J2796trl27Kjw8XE2bNpUktWvXTlu2bFGZMmXk5+enZs2aaejQoUpNTbVeNAokJSVp4MCBKlWqlN5++205ODgof/78OnfunPz8/BQWFqbq1atr2LBhio2NVUhIiCIjI7V9+3Zt3LhRRYsWtXUKAHAXCuOPmFudccMwNHbsWDVr1kxS9qvUOVGHhIQE1axZU/Xr19eyZcvk7Owss9ksi8Wi6OhoDRs2THv37tWBAwdUtWpVpaWlycnJSdLN7ebObYntCH+FfRJyA9sR/o4/fydZLBZ9//336t27twoWLHhXcTwiIkIXL15Ux44dtWrVqv+z+InHy7fffqvAwED98ssvevLJJ3Ocm16STp06pWrVqll/59gIeLydO3dO/fv3l7Ozs1avXq3ChQvbOiQAALJJTk5WcHCw2rRpY533+caNGxo0aJCqV6+uESNGaOrUqZo0aZK2bdumuLg4bd++XR999JGOHDmiWrVq2TgD5BWGYah///5asmSJJCkwMFCVK1dWp06d1Lx5c02bNk0xMTGaOXOmTpw4oUmTJik2NlZly5bVgAED1KRJExtnAAA5ozD+COJKdfyV9PR01apVSx4eHoqIiLC233nC98SJE+rYsaOqVq2qdevWSZL1StJ7nRgG7oV9EnID2xH+SnJyssaPHy9PT0+9/PLLcnJyUrFixSRJhw8fVrdu3eTm5qbIyEgZhqEePXro888/lyQtX75c3bt3p6CJbC5cuKDq1atr/vz56t+/f47LrFixQnPnztXOnTtVoECBhxwhgLwqKipK8fHxql+/vq1DAQAgG8MwNHjwYP3nP/9R69at1aVLF2txfPbs2Vq4cKHat2+vefPm6bPPPlPHjh2t68XGxsrT09OW4SMPOnv2rEaNGiWTyaQiRYrIx8dHkydPVkhIiE6dOqXz589rw4YNKlu2rE6cOKG3335bEyZMUJ06dWwdOgDcE9WvR1DFihX14YcfKjExUe+9957++OMPW4eEPMRkMql69eo6c+aMDh48KOnuYrevr6+efvppXbp0SSaTKdvwShTFcb/YJyE3sB3hXgzD0JAhQzRr1iyNGjVKzz33nFq0aKGpU6dq8+bN8vPz07Jly5QvXz7Vr19fDg4OCg0N1auvvqovv/zSWhQH7uTs7Kxy5crp888/14kTJ6ztd24rcXFxql27thwdHW0RIoA8qlKlShTFAQB5kslkUqVKlSRJTk5OWrNmjZYuXSpJGj58uDw8PDR37lytXLnSWhS/td6tojh9J9ypcuXK+uCDDyTdnI7qhRde0HfffSeTyaTY2Fj997//1XfffSfDMOTr66sVK1ZQFAeQ53HH+COMK9Vxp5SUFAUHB2vFihU5zrN66065W/+OHTtW69ev19GjRznhi1zBPgm5ge0IOYmKilJISIgkqXbt2vLy8tKSJUt0/vx5VahQQd7e3vL19dX777+v+vXra9++fdaLwhiGHxaLRYmJiTp69KiKFSum0qVLy93dXevXr1eHDh3UuXNnjRw5Un5+fpJujr6zdOlSjRs3TsuWLVNgYKCNMwAAAAD+2p3zinfp0kWFChVSXFycrl27puDgYPXs2VMzZszQ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f3Rnf7pr165yc3PTunXrVKpUKesyfy4Uh4eHy8PDQ88884y1j/3bb7+pXr16cnNzs041tm3bNiUmJmr06NF3zQd+q4+dk0KFCik5OVnbtm3723kcPnxYsbGxGjRoULbXatu2rapUqaLNmzfftc5rr72W7fdmzZrpxx9//NuvCQDAo4A7xgEAsDMfffSRKlWqpPj4eC1evFh79uyx3hl+/vx5GYahcePGWa8E/7PY2FiVKlVKFy5csA4L91eWLl2qmTNn6syZM9mGiCtbtmzuJAQAAAAAwENwqz/t6OgoT09PVa5cWQ4Ot+8tc3R0lJeXV7Z1zp07p/j4eBUvXjzH54yNjZV0e1j2GjVq3FdMgwYN0urVq9WmTRuVKlVKgYGBeumll9S6det7rvPTTz9JkipXrnzXY1WqVNG+ffuytbm4uKhYsWLZ2goXLpzjHOkAADzKKIwDAGBnGjRoID8/P0nSCy+8oKZNm6p79+46e/assrKyJElvvvmmgoKCcly/QoUKf/u1li9frj59+uiFF17QiBEjVLx4cev8Zbc6/QAAAAAAPAru7E/nJF++fNkK5dLN0dOKFy+uFStW5LjOnwvO96t48eI6evSotm7dqq+++kpfffWVlixZol69emnp0qX/03Pf8neHaAcA4FFHYRwAADt2q0jdsmVLzZ8/X/369ZMkOTk5KSAg4C/XLV++vE6ePPmXy6xZs0blypXTF198kW3ot/Hjx//vwQMAAAAAkMeVL19e27dv11NPPSVXV9e/XE6STp48eV8XpEuSs7OznnvuOT333HPKysrSoEGDtGDBAo0bNy7H5ypTpowk6ezZs3r66aezPXb27Fnr4wAAPG6YYxwAADvXokULNWjQQHPmzFHBggXVokULLViwQFeuXLlr2bi4OOv/d+rUSceOHdO6devuWs4wDEm3ryq/9bskHTx4UAcOHMjtNAAAAAAAyHNeeuklWSwWTZo06a7HMjMzdf36dUlSYGCg3N3dNWXKFKWmpmZb7s4+9Z/9/vvv2X53cHBQzZo1JUlpaWk5ruPn56fixYvr448/zrbMV199pdOnT6tt27Z/KzcAAOwNd4wDAPAYGDFihF588UWFhobqo48+UtOmTeXr66sBAwaoXLlyiomJ0YEDB/TLL7/o2LFj1nXWrFmjF198Uf369VO9evV07do1bdiwQR9//LFq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8ssvdz22ZMkS+fn5qWbNmjaILDvDMJSZmWnrMAAAAAAA+Mfog+eMwjgAAAAA4IFr166dihUrZh0h7JakpCSFh4crODhY+/btU7NmzeTq6ipvb28NHTpUycnJ1mXT0tI0atQoeXt7K1++fKpQoYIWLVqk6Oho6zRdhQsXlslkso4ulpaWpqFDh6p48eJycXFR06ZNdejQIetz3rrK/auvvlK9evWUL18+7du374G/HwAAAAAAPCj0wXNGYRwAAAAA8MA5OjqqV69eCg0NlWEY1vbw8HBZLBY1btxYrVu3VqdOnXT8+HGFhYVp3759Gjx4sHXZXr16adWqVfrwww91+vRpLViwQG5ubvL29tbatWslSWfPntWVK1c0d+5cSdLIkSO1du1aLV26VJGRkapQoYKCgoJ07dq1bPGNHj1aU6dO1enTp/PEVfMAAAAAAPxT9MFzZjLufDceAwkJCfLw8FB8fLwKFixo63AAAP+LCR62jiAb37KlbR3CXU70PmHrEAAAD0BqaqouXryosmXLysXF5fYDD/u7cUL8fS1+5swZVa1aVTt37lSLFi0kSc2bN1eZMmWUL18+mc1mLViwwLr8vn375O/vr+TkZP3888+qXLmytm3bpoCAgLuee9euXWrZsqX++OMPFSpUSJKUnJyswoULKzQ0VN27d5ckZWRkyMfHR8OGDdOIESOs63355Zdq3779feVzr8+BfudtvBcAcuK71NfWIWRDvwkAANzLPfvf0sPtg99n/1uyrz74X30O99Pv5I5xAAAAAMBDUaVKFTVp0kSLFy+WJJ0/f1579+5VcHCwjh07ptDQULm5uVl/goKClJWVpYsXL+ro0aMym83y9/f/26934cIFZWRk6KmnnrK2OTk5qUGDBjp9+nS2Zf38/HInSQAAAAAA8gD64HejMA4AAAAAeGiCg4O1du1aJSYmasmSJSpfvrz8/f2VlJSkV199VUePHrX+HDt2TOfOnVP58uXl6ur6QOMqUKDAA31+AAAAAAAeNvrg2VEYBwAAAAA8NC+99JIcHBy0cuVKLVu2TP369ZPJZFLdunV16tQpVahQ4a4fZ2dn+fr6KisrS7t3787xeZ2dnSVJFovF2la+fHk5Oztr//791raMjAwdOnRI1apVe7CJAgAAAABgY/TBs6MwDgAAAAB4aNzc3NSlSxe99dZbunLlivr0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+fOzcePGbNu2rXnM7NmzM3v27DzyyCPp6elpxufNm5fp06fnwQcfzJ49e5rxBQsWZOrUqVm3bt2QizILFy5Md3d31q5dO2QMixcvTm9vb9avX9+MVavVLFmyJD09PXnooYea8YkTJ2bRokV55plnhuzYnzJlSs4444xs3rw5mzZtasblJKf+nMZVkvecPnBxL0m+/Gglx3Ul7zx1IN7XSL78aDWzJicXzR6IP9ebfG1jNadPKfOmmQMX/TbtTm57sprXnFTmtScNxB/uKfLdLUXeMKPMz08ZiN/3bJF7nylywexG1h7//oGctn0n03c+mAdnvSt7ul82kNNT38jUPT/KuldekXploAm+8Mk/S3dtZ9aeOnAfSbJ4443p7To+6+dc1oxVG71Z8viN6Zn4ijx0yiXN+MTe7Vm06St55vhX5bGTL0iSLJs0MU/Vn8rqn63OmePOzMLuhc3jN/RtyD2992RJ95KcNu60Znx97/qs71ufN094c06pntKM37P3nmyobchFEy/KlMqUZnz1z1bnqfpTuWTSJRk3qFF/y+5bsrvcnWWTlzVja9euPeprrxN/n+QkJznJSU5ykpOcDian+++/PwerKAe31g9BWZb5zne+k/vvv7+Z8Bvf+MYXc1cvqR07dmTKlCnp6enJCSec0OrhvKC5K29t9RCGeXzCu1o9hGHOOvUVrR7CEA9c/kCrhzBMu9WSOjo47VZL7VZHSfvVkjo6OO1WS+1WR4laOhjtVkdJ+9WSOjo47VZL7VZHSfvVUjvW0f7G+rxzLM6/N2/enFmzZuWuu+7Keeed14x/+MMfzp133pnvfe97I96up6cns2bNyt69e1OtVvP5z38+//7f//tRf85IO8bnzJmTZ599tvlvYceDnDo5p1OvurXtdow/NGH5QE5tsmN86dw5bbVjfM2la4762htp7HKSk5zkJCc5yUlOx0JO27dvz0knnXRQ5+CHtGP87rvvzrPPPptf+7VfS1EUeetb35qnnnoq11xzTXbv3p23v/3t+dznPpfx48cfyt0CAAAAg7TL+ffxxx+f73//+/npT3+a1atXZ8WKFZk3b96wt1nvN378+BHH1NXVla6uoZcg+i9u7K//AszBxve/3xcTL4pixPhoYzzUuJyOpZyK9DWGR8tklPjIxzdSpDFSvCzSGGGLS70sUh8hXiuLdJW9w+L7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IcfCaPrr49prr81pp52Wu+66K7fddls2btyYl7/85fmTP/mT/Omf/mn27t3rhIpRlWXZbIovXLgwb3zjG0dtint7QF5I/0n3b//2b+f000/P//2//zdbtmzJJz7xiTz99NP5nd/5ndxzzz3mI15Q/zpp9+7decMb3pCPfvSj+djHPpZdu3alUqmYh+AY9NOf/jSvfvWr8wu/8AvNpvgDDzyQ22+/PY888kh+8pOfNJ+DYDR79+7Nb/7mb+aHP/xhHnroodxwww3ZsGFDq4fFUai3tzf/6l/9q5x66qn5+te/nq9//es5++yz82/+zb/Jl770pTzzzDOtHiJHgd27d+cXf/EX85rXvCZ/93d/l7vuuisLFy7Mhg0bUqlUmudMnts4kF27duWcc87Jk08+mSVLluTHP/5x/tt/+2955zvf2WyKqyMO5Gc/+1le//rXZ9KkSfnQhz6Uj370o/nrv/7rXHPNNVm1alWrh8cY8VbqvGjPPfdcdu/enY9//OOZO3du5s6dmyVLlmTBggV573vfm+7u7nz2s5910ZdRFUWR3t7eXHLJJXnNa16Tv/zLv0xXV1fe+MY3ZvXq1ent7c3jjz+euXPnemUfL6h/ntmxY0cmTZqURqORsixz3HHHZdWqVXnve9+br3zlKzn11FPza7/2a3bSMKKiKPKzn/0sCxYsyKte9ap8/etfT5J87nOfyw9+8IPs3r07r33ta/OhD32oeUJlTmI0/c9h//pf/+tMmzYtSfLe9743p556aj73uc/l93//9/P5z38+r371q1s8UtpVURSp1Wr53d/93Zx00kn5xV/8xdxzzz256qqrct1119k5Dsegz3/+8/nxj3+cj370o0mS5cuX57777svDDz+cWbNm5ayzzsp//a//NfPnz7feZVT33HNPdu7cma9+9at54IEHcvPNNydJPvShD9k5ziHZtm1bnnnmmVx77bVZtGhRkuT1r399Vq5cmc985jPp7u7Oe9/73owbN67FI6WdffWrX82sWbNy/fXXN2vl537u53LXXXfl3/27f5eXv/zlec973pNXvepV1r68oL/927/NSSedlG984xs57rjj0tfXl69+9av59Kc/nbe+9a353//7f/szixzQP/3TP6Usy3zpS19qXss599xz85nPfCaf//zn093dnXe84x0tHiWHyzMJh+XRRx/NQw89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6YOrqytff/01J0+eZNasWRw/fpw1a9bQoUMHZ4csIiIiIiIiIiIiIiJyU6gwLiJSjeTl5RETE8P58+dZvnw57du3B6C8vByz2cy1a9coKirCx8fHyZGKiIiIiIiIiIiIiIjcPCqMi4hUM/n5+YwcORLDMHjllVcIDg4GwGazOe4fFxERERERERERERERuZ2oMC4iUg3l5eUxatQoTCYTcXFxdOrUydkhiYiIiIiIiIiIiIiI/GZUGBcRqaby8vKIiorCYrGwdu1a6tSp4+yQREREREREREREREREfhMqjIuIVGMnTpzgypUrtGnTxtmhiIiIiIiIiIiIiIiI/GZUGBcRERERERERERERERERkduaq7MDEBERERERERERERERERER+S2pMC4iIiIiIiIiIiIiIiIiIrc1FcZFREREREREREREREREROS2psK4iIiIiIiIiIiIiIiIiIjc1lQYFxERERERERERERERERGR25oK4yIiIiIiIiIiIiIiIiIicltTYVxERERERERERERERERERG5rKoyLiIiIiIiIiIiIiIiIiMhtTYVxERERERERERERERERERG5rakwLiIiIiIiIiIiIiIiIiIit7X/D2qfsHAVSEEyAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_search_method_comparison(\n", + " lexical_search_metric_dicts,\n", + " vector_search_metric_dicts,\n", + " hybrid_search_metric_dicts,\n", + " metric_names\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "oeERj6U4oMj9" + }, + "source": [ + "# **Step 10: Storing Evaluation Results In MongoDB**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "ELaECcHDoQnI" + }, + "outputs": [], + "source": [ + "from datetime import datetime\n", + "\n", + "\n", + "def store_evaluation_results(db: Any, search_method: str, metrics: Dict[str, Dict[str, float]], additional_info: Dict[str, Any] | None = None):\n", + " \"\"\"\n", + " Store evaluation results in MongoDB.\n", + "\n", + " Args\n", + " db: MongoDB database instance\n", + " search_method: Name of the search method (e.g., 'lexical', 'vector', 'hybrid')\n", + " metrics: Dictionary containing evaluation metrics (ndcg, map, recall, precision)\n", + " additional_info: Optional dictionary for any additional information to store\n", + " \"\"\"\n", + " collection = db['evaluation_results']\n", + "\n", + " # Prepare the document to be inserted\n", + " result_doc = {\n", + " \"timestamp\": datetime.utcnow(),\n", + " \"search_method\": search_method,\n", + " \"metrics\": {}\n", + " }\n", + "\n", + " # Add metrics to the document\n", + " for metric_name, metric_values in metrics.items():\n", + " result_doc[\"metrics\"][metric_name] = metric_values\n", + "\n", + " # Add any additional information\n", + " if additional_info:\n", + " result_doc.update(additional_info)\n", + "\n", + " # Insert the document\n", + " insert_result = collection.insert_one(result_doc)\n", + "\n", + " print(f\"Evaluation results for {search_method} stored with ID: {insert_result.inserted_id}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "oMcDhx-9oqQG" + }, + "outputs": [], + "source": [ + "metadata = {\n", + " \"dataset_name\": DATASET,\n", + " \"corpus_size\": len(corpus),\n", + " \"num_queries\": len(queries),\n", + " \"num_qrels\": sum(len(q) for q in qrels.values())\n", + "}\n", + "\n", + "information_retrieval_eval_metrics_list = [\n", + " lexical_search_metric_dicts,\n", + " vector_search_metric_dicts,\n", + " hybrid_search_metric_dicts,\n", + "]\n", + "\n", + "# Iterate through metrics list and store evaluation results\n", + "for search_method, metrics in zip(information_retrieval_search_methods, information_retrieval_eval_metrics_list):\n", + " store_evaluation_results(db, search_method, metrics, metadata)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lCicxbn3sZAT" + }, + "source": [ + "# **Evaluating on the Financial Opinion Mining and Question Answering (FIQA) dataset**\n", + "\n", + "\n", + "\n", + "---\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 81, + "referenced_widgets": [ + "879141a9900d4741985af9ee5f230760", + "5f822791ad0243d99cffb09f57b6257d", + "f9596cf74c4b428594a0be76406d96be", + "b014d38bd40740a18eaf90a6d2f69439", + "6a3ffc1cb8764532b215d51cae6e44be", + "13eec1cf9f3b4e27995eb7735bbf43aa", + "8bda824cef9c493b83704d511554954c", + "9903eb80686c492aa8a5e3190ccc798a", + "148567c981e74f1a9b840fb5463f6c1f", + "2001c71b7c0649ad94991dc00c2c1c2b", + "0b639c296a6e42e883957f4053e08881", + "ef9546a04f6d47e081b7021376e1fdab", + "f2be4ffe3b984e9989af25faceb3c9fc", + "4cbd2428f91c40d092e1c3bc80171123", + "72b0800f217f4559aea1c0db64d6594c", + "983b3ad86d71468c9efc7e01926c70e6", + "e260dd2233ff479db1471ec42f0b907a", + "b446bbe72b8344dab8c5b637ff3e48bf", + "fbf3da22c9954c3ab5995fff682084ba", + "6a61062dbe92469889f767985c4f5b59", + "e71944737601445a9e8a1f39fe32d445", + "edd9d4c3787f44e2a6d7fe43dec354f2" + ] + }, + "id": "KYdzVpcXshVO", + "outputId": "a1068432-aea5-44c3-c194-ad7fa33e45dc" + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "879141a9900d4741985af9ee5f230760", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "datasets/fiqa.zip: 0%| | 0.00/17.1M [00:00" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_search_method_comparison(\n", + " lexical_search_metric_dicts,\n", + " vector_search_metric_dicts,\n", + " hybrid_search_metric_dicts,\n", + " metric_names\n", + ")" + ] + } + ], + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "00135b96c1e34abf94352e5d14dfbfc2": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "0b639c296a6e42e883957f4053e08881": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "13eec1cf9f3b4e27995eb7735bbf43aa": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "148567c981e74f1a9b840fb5463f6c1f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "2001c71b7c0649ad94991dc00c2c1c2b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "30ccab778b894d8c86359fb850ee76f2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b7df766690574c09b4942e0d27151171", + "max": 5183, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_e65a397cb2e44371886c3f51362a9bc6", + "value": 5183 + } + }, + "33ef6c005a52428cb00a9e7ccb0e6b2c": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "350c3f298a7b414c8ab6ea4492fb98c3": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "35b668058eca435a86829f32ca421859": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_33ef6c005a52428cb00a9e7ccb0e6b2c", + "max": 2816079, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_b8c4d550a4fb475d8a66c1e5deefb1f2", + "value": 2816079 + } + }, + "4950b546681b4c8cbec0a9c3acf08c37": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_350c3f298a7b414c8ab6ea4492fb98c3", + "placeholder": "​", + "style": "IPY_MODEL_6275b672934d4cc383cc4c18f3dfe4b7", + "value": "100%" + } + }, + "4cbd2428f91c40d092e1c3bc80171123": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_fbf3da22c9954c3ab5995fff682084ba", + "max": 57638, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_6a61062dbe92469889f767985c4f5b59", + "value": 57638 + } + }, + "51c3a472109243c681898fb32aeda7d7": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_f22b82b8010a4a79b0b42908966cc89e", + "IPY_MODEL_35b668058eca435a86829f32ca421859", + "IPY_MODEL_84d25add023044d68f383b81dacaf462" ], - "source": [ - "corpus_text_index_definition = {\n", - " \"mappings\": {\n", - " \"dynamic\": True,\n", - " \"fields\": {\n", - " \"text\": {\n", - " \"type\": \"string\"\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "create_collection_search_index(db[fiqa_corpus], corpus_text_index_definition, TEXT_SEARCH_INDEX)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "44aXUJtJuqA_", - "outputId": "f6ed0498-1875-4eb5-b870-331e14049a86" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Checking for documents without embeddings...\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Identifying documents to embed: 100%|██████████| 57638/57638 [00:00<00:00, 133048.67it/s]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Found 56487 documents without embeddings out of 57638 total documents.\n", - "Generating embeddings for documents without them...\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Embedding documents: 100%|██████████| 56487/56487 [5:25:18<00:00, 2.89it/s]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "New embeddings generated and stored successfully.\n", - "Total documents with embeddings: 57638\n" - ] - } + "layout": "IPY_MODEL_c3375ea1a272481babcaece7f79b428e" + } + }, + "5b4d7df8ac4e4a788d7684f47f1d1b76": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "5f822791ad0243d99cffb09f57b6257d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_13eec1cf9f3b4e27995eb7735bbf43aa", + "placeholder": "​", + "style": "IPY_MODEL_8bda824cef9c493b83704d511554954c", + "value": "datasets/fiqa.zip: 100%" + } + }, + "6275b672934d4cc383cc4c18f3dfe4b7": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "6770f34c4be644cda13221e47d00ca28": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "6a3ffc1cb8764532b215d51cae6e44be": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "6a61062dbe92469889f767985c4f5b59": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "72b0800f217f4559aea1c0db64d6594c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e71944737601445a9e8a1f39fe32d445", + "placeholder": "​", + "style": "IPY_MODEL_edd9d4c3787f44e2a6d7fe43dec354f2", + "value": " 57638/57638 [00:00<00:00, 91199.90it/s]" + } + }, + "7350acfbe3bd4e1cb4ff49290a6cd58f": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "73cddc3fa8bb4495b335018fae3b063e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_4950b546681b4c8cbec0a9c3acf08c37", + "IPY_MODEL_30ccab778b894d8c86359fb850ee76f2", + "IPY_MODEL_c25ebc49169a4fccae65c84ba71b50c7" ], - "source": [ - "generate_and_store_embeddings(corpus, db, fiqa_corpus)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "p2xuo3K-vkyc" - }, - "outputs": [], - "source": [ - "# Define information retrieval mechanisims\n", - "\n", - "lexical_search = MongoDBSearch(db[fiqa_corpus], \"text_search_index\")\n", - "\n", - "vector_store = MongoDBAtlasVectorSearch.from_connection_string(\n", - " connection_string=MONGO_URI,\n", - " namespace=f\"{DB_NAME}.{fiqa_corpus}\",\n", - " embedding=embedding_model,\n", - " index_name=\"vector_index\",\n", - " text_key=\"text\"\n", - ")\n", - "\n", - "vector_search = MongoDBVectorSearch(vector_store, embedding_model)\n", - "\n", - "hybrid_search = MongoDBHybridSearch(vector_store, \"text_search_index\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "po0V50FUv5MJ" - }, - "outputs": [], - "source": [ - "def evaluate_search_method(search_method, method_name):\n", - " retriever = EvaluateRetrieval(search_method, score_function=\"dot\")\n", - " results = retriever.retrieve(corpus, queries)\n", - " metrics = retriever.evaluate(qrels, results, retriever.k_values)\n", - "\n", - " print(\"Sample of retrieved results:\")\n", - " for query_id, doc_scores in list(results.items())[:5]:\n", - " print(f\"Query ID: {query_id}\")\n", - " print(f\"Query text: {queries[query_id]}\")\n", - " print(\"Top 3 retrieved documents:\")\n", - " for doc_id, score in list(doc_scores.items())[:3]:\n", - " print(f\" Doc ID: {doc_id}, Score: {score}\")\n", - " print()\n", - "\n", - " print(f\"\\nResults for {method_name}:\")\n", - " ndcg, _map, recall, precision = metrics\n", - " for metric, values in zip([\"NDCG\", \"MAP\", \"Recall\", \"Precision\"], [ndcg, _map, recall, precision]):\n", - " print(f\"{metric}:\")\n", - " for k, v in values.items():\n", - " print(f\" {k}: {v:.4f}\")\n", - "\n", - " # Store results in MongoDB (assuming you've defined this function)\n", - " store_evaluation_results(db, method_name, {\n", - " \"ndcg\": ndcg,\n", - " \"map\": _map,\n", - " \"recall\": recall,\n", - " \"precision\": precision\n", - " }, {\"dataset\": \"FiQA\"})\n", - "\n", - " return [ndcg, _map, recall, precision]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "LOGPKVU5v6iZ", - "outputId": "121270e1-0477-4e7e-9d00-962fc52f1b80" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sample of retrieved results:\n", - "Query ID: 8\n", - "Query text: How to deposit a cheque issued to an associate in my business into my business account?\n", - "Top 3 retrieved documents:\n", - " Doc ID: 65404, Score: 15.907803535461426\n", - " Doc ID: 318108, Score: 12.162151336669922\n", - " Doc ID: 508754, Score: 11.79505443572998\n", - "\n", - "Query ID: 15\n", - "Query text: Can I send a money order from USPS as a business?\n", - "Top 3 retrieved documents:\n", - " Doc ID: 420483, Score: 10.010725021362305\n", - " Doc ID: 230003, Score: 9.536849021911621\n", - " Doc ID: 224000, Score: 8.561530113220215\n", - "\n", - "Query ID: 18\n", - "Query text: 1 EIN doing business under multiple business names\n", - "Top 3 retrieved documents:\n", - " Doc ID: 377152, Score: 10.069451332092285\n", - " Doc ID: 348480, Score: 8.927388191223145\n", - " Doc ID: 203820, Score: 8.656691551208496\n", - "\n", - "Query ID: 26\n", - "Query text: Applying for and receiving business credit\n", - "Top 3 retrieved documents:\n", - " Doc ID: 176284, Score: 7.173275947570801\n", - " Doc ID: 338406, Score: 6.504555702209473\n", - " Doc ID: 227910, Score: 6.3861494064331055\n", - "\n", - "Query ID: 34\n", - "Query text: 401k Transfer After Business Closure\n", - "Top 3 retrieved documents:\n", - " Doc ID: 231449, Score: 6.630157470703125\n", - " Doc ID: 494783, Score: 6.015130996704102\n", - " Doc ID: 232049, Score: 5.856289863586426\n", - "\n", - "\n", - "Results for Lexical Search:\n", - "NDCG:\n", - " NDCG@1: 0.2253\n", - " NDCG@3: 0.2041\n", - " NDCG@5: 0.2144\n", - " NDCG@10: 0.2389\n", - " NDCG@100: 0.2933\n", - " NDCG@1000: 0.3287\n", - "MAP:\n", - " MAP@1: 0.1104\n", - " MAP@3: 0.1543\n", - " MAP@5: 0.1659\n", - " MAP@10: 0.1791\n", - " MAP@100: 0.1920\n", - " MAP@1000: 0.1936\n", - "Recall:\n", - " Recall@1: 0.1104\n", - " Recall@3: 0.1895\n", - " Recall@5: 0.2303\n", - " Recall@10: 0.3004\n", - " Recall@100: 0.5061\n", - " Recall@1000: 0.7272\n", - "Precision:\n", - " P@1: 0.2253\n", - " P@3: 0.1327\n", - " P@5: 0.0988\n", - " P@10: 0.0665\n", - " P@100: 0.0121\n", - " P@1000: 0.0018\n", - "Evaluation results for Lexical Search stored with ID: 66ee1142726b94bb9861083a\n", - "Sample of retrieved results:\n", - "Query ID: 8\n", - "Query text: How to deposit a cheque issued to an associate in my business into my business account?\n", - "Top 3 retrieved documents:\n", - " Doc ID: 65404, Score: 0.8552490472793579\n", - " Doc ID: 188893, Score: 0.8239511251449585\n", - " Doc ID: 590102, Score: 0.8056215643882751\n", - "\n", - "Query ID: 15\n", - "Query text: Can I send a money order from USPS as a business?\n", - "Top 3 retrieved documents:\n", - " Doc ID: 325273, Score: 0.8300462961196899\n", - " Doc ID: 284528, Score: 0.8076863884925842\n", - " Doc ID: 224000, Score: 0.8001105785369873\n", - "\n", - "Query ID: 18\n", - "Query text: 1 EIN doing business under multiple business names\n", - "Top 3 retrieved documents:\n", - " Doc ID: 377152, Score: 0.8017109632492065\n", - " Doc ID: 78486, Score: 0.786155104637146\n", - " Doc ID: 431685, Score: 0.7809617519378662\n", - "\n", - "Query ID: 26\n", - "Query text: Applying for and receiving business credit\n", - "Top 3 retrieved documents:\n", - " Doc ID: 500755, Score: 0.8401659727096558\n", - " Doc ID: 274832, Score: 0.8234261870384216\n", - " Doc ID: 336468, Score: 0.8188062906265259\n", - "\n", - "Query ID: 34\n", - "Query text: 401k Transfer After Business Closure\n", - "Top 3 retrieved documents:\n", - " Doc ID: 492659, Score: 0.8165256977081299\n", - " Doc ID: 458917, Score: 0.8110530376434326\n", - " Doc ID: 554739, Score: 0.8083138465881348\n", - "\n", - "\n", - "Results for Vector Search:\n", - "NDCG:\n", - " NDCG@1: 0.3858\n", - " NDCG@3: 0.3553\n", - " NDCG@5: 0.3648\n", - " NDCG@10: 0.3942\n", - " NDCG@100: 0.4652\n", - " NDCG@1000: 0.4963\n", - "MAP:\n", - " MAP@1: 0.2005\n", - " MAP@3: 0.2774\n", - " MAP@5: 0.2978\n", - " MAP@10: 0.3182\n", - " MAP@100: 0.3371\n", - " MAP@1000: 0.3388\n", - "Recall:\n", - " Recall@1: 0.2005\n", - " Recall@3: 0.3216\n", - " Recall@5: 0.3751\n", - " Recall@10: 0.4653\n", - " Recall@100: 0.7304\n", - " Recall@1000: 0.9186\n", - "Precision:\n", - " P@1: 0.3858\n", - " P@3: 0.2325\n", - " P@5: 0.1688\n", - " P@10: 0.1093\n", - " P@100: 0.0184\n", - " P@1000: 0.0024\n", - "Evaluation results for Vector Search stored with ID: 66ee12e0726b94bb9861083b\n", - "Sample of retrieved results:\n", - "Query ID: 8\n", - "Query text: How to deposit a cheque issued to an associate in my business into my business account?\n", - "Top 3 retrieved documents:\n", - " Doc ID: 65404, Score: 1.0\n", - " Doc ID: 590102, Score: 0.999\n", - " Doc ID: 261856, Score: 0.998\n", - "\n", - "Query ID: 15\n", - "Query text: Can I send a money order from USPS as a business?\n", - "Top 3 retrieved documents:\n", - " Doc ID: 224000, Score: 1.0\n", - " Doc ID: 325273, Score: 0.999\n", - " Doc ID: 28974, Score: 0.998\n", - "\n", - "Query ID: 18\n", - "Query text: 1 EIN doing business under multiple business names\n", - "Top 3 retrieved documents:\n", - " Doc ID: 377152, Score: 1.0\n", - " Doc ID: 431685, Score: 0.999\n", - " Doc ID: 203820, Score: 0.998\n", - "\n", - "Query ID: 26\n", - "Query text: Applying for and receiving business credit\n", - "Top 3 retrieved documents:\n", - " Doc ID: 176284, Score: 1.0\n", - " Doc ID: 274832, Score: 0.999\n", - " Doc ID: 336468, Score: 0.998\n", - "\n", - "Query ID: 34\n", - "Query text: 401k Transfer After Business Closure\n", - "Top 3 retrieved documents:\n", - " Doc ID: 122114, Score: 1.0\n", - " Doc ID: 232049, Score: 0.999\n", - " Doc ID: 174335, Score: 0.998\n", - "\n", - "\n", - "Results for Hybrid Search:\n", - "NDCG:\n", - " NDCG@1: 0.3518\n", - " NDCG@3: 0.3203\n", - " NDCG@5: 0.3386\n", - " NDCG@10: 0.3626\n", - " NDCG@100: 0.4363\n", - " NDCG@1000: 0.4698\n", - "MAP:\n", - " MAP@1: 0.1782\n", - " MAP@3: 0.2458\n", - " MAP@5: 0.2694\n", - " MAP@10: 0.2859\n", - " MAP@100: 0.3055\n", - " MAP@1000: 0.3075\n", - "Recall:\n", - " Recall@1: 0.1782\n", - " Recall@3: 0.2918\n", - " Recall@5: 0.3595\n", - " Recall@10: 0.4320\n", - " Recall@100: 0.7044\n", - " Recall@1000: 0.9081\n", - "Precision:\n", - " P@1: 0.3518\n", - " P@3: 0.2099\n", - " P@5: 0.1599\n", - " P@10: 0.1009\n", - " P@100: 0.0176\n", - " P@1000: 0.0023\n", - "Evaluation results for Hybrid Search stored with ID: 66ee14d9726b94bb9861083c\n" - ] - } + "layout": "IPY_MODEL_00135b96c1e34abf94352e5d14dfbfc2" + } + }, + "84d25add023044d68f383b81dacaf462": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_c45d82a40d2c4096b6c00b6c93290add", + "placeholder": "​", + "style": "IPY_MODEL_9cbf8f18e9dd4cd3acc274ad3f4868ae", + "value": " 2.69M/2.69M [00:00<00:00, 6.83MiB/s]" + } + }, + "879141a9900d4741985af9ee5f230760": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_5f822791ad0243d99cffb09f57b6257d", + "IPY_MODEL_f9596cf74c4b428594a0be76406d96be", + "IPY_MODEL_b014d38bd40740a18eaf90a6d2f69439" ], - "source": [ - "# Run evaluations\n", - "lexical_search_metric_dicts = evaluate_search_method(lexical_search, \"Lexical Search\")\n", - "vector_search_metric_dicts = evaluate_search_method(vector_search, \"Vector Search\")\n", - "hybrid_search_metric_dicts = evaluate_search_method(hybrid_search, \"Hybrid Search\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "id": "UbteGcX8wLPz", - "outputId": "43432477-f8af-4bb9-c443-d247b43de06d" - }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAB8YAAAYkCAYAAACY/GVtAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzde1yUdfr/8fc9M5xRPIIKJIiWmiIlanbS0lIr2zI3s4NIru2vsq21srQyTVut7WC1ptvB1NLN7OB21DU2/GaYpWLoekrFzPCAmqCAHGbu3x/GyDCDogEzDK+nDx6PuO7DXNfcn27mM9fc9ximaZoCAAAAAAAAAAAAAMBPWbydAAAAAAAAAAAAAAAAtYnGOAAAAAAAAAAAAADAr9EYBwAAAAAAAAAAAAD4NRrjAAAAAAAAAAAAAAC/RmMcAAAAAAAAAAAAAODXaIwDAAAAAAAAAAAAAPwajXEAAAAAAAAAAAAAgF+jMQ4AAAAAAAAAAAAA8Gs0xgEAAAAAAAAAAAAAfo3GOAAAAAC/s3z5cqWmpurcc89V48aNFRQUpNatW+uqq67Siy++qNzcXG+nWK/s2rVLhmEoLi7O26n4hIyMDF199dVq1qyZLBaLDMPQ3Llzq7Xt3r179eijjyopKUmNGjVSYGCg2rRpowsuuECjR4/W3LlzZbfba7eAOjZp0iQZhqFJkybV2D7Lx2T5z0cffXTK9a+99lrnuv3796+xPE6nb9++MgxD6enpdfaYpxIXFyfDMLRr1y5vpwIAAAAAdc7m7QQAAAAAoKYcPHhQw4cP15dffinpRBPoiiuuUFhYmPbt26eMjAx9+eWXmjhxor788kv16tXLyxmjvsnJydG1116rvLw8XXrppYqLi5PFYlH79u1Pu21GRoauvfZaHTlyROHh4erZs6eioqJ07NgxbdiwQW+88YbeeOMNDR06VOHh4XVQjf+YM2eObrzxRo/LfvnlFy1btqzGH3Pu3LlKTU1VSkpKtT8YAQAAAADwHhrjAAAAAPxCeaNy69at6tixo1577TVddtllLusUFxdr3rx5evLJJ7V3714vZVr/REdHa/PmzQoICPB2Kl73n//8R0eOHNGtt96qBQsWVHu74uJi3Xzzzc5tZ82apcaNG7uss2XLFs2ZM0dWq7Wm0/ZbVqtVXbt21dKlS7Vv3z61atXKbZ158+bJbrerR48e+v77772QJQAAAADAF3ArdQAAAAB+4b777tPWrVsVFxenb775xq0pLklBQUG66667tH79enXq1MkLWdZPAQEB6tixoxISEryditft3r1bktShQ4cz2m7lypX65ZdfZLPZ9Nprr7k1xSWpY8eOevbZZxUSElIjuTYUd955p8rKyjRv3jyPy9966y0FBwfr1ltvrePMAAAAAAC+hMY4AAAAgHpv586dWrhwoSTphRdeULNmzU65flRUlM477zy3+Lvvvqt+/fqpWbNmCgoKUtu2bXXnnXdq27ZtHvdT8ft6v/jiC/Xt21cRERFq2rSprrvuOm3YsMG57sKFC9W7d281atRITZo00ZAhQ7Rjxw63faanp8swDPXt21eFhYWaMGGC2rdvr+DgYLVp00ajRo3SL7/84jGfL7/8Uvfdd5+SkpLUokULBQUFKSYmRsOGDavyStmK3/+8e/dujRo1SrGxsQoICNDIkSMlnfo7xn/88Ufdeeedio+PV1BQkMLDw9W2bVtde+21euuttzw+5rJly3TdddcpMjLS+R3bw4YN05o1azyuX/F7mtevX68hQ4Y46+vcubOef/55mabpcdvTqe4xnzt3rgzD0JNPPilJmjx5svM7q6vz3ev79++XJIWHhyssLOyscn3//fc1cOBAtWzZUoGBgYqOjtbtt9+uTZs2eVy/tsaDJJmmqQ8//FDXXXedWrVqpcDAQLVq1UqXXnqpnnnmGRUVFXncf25uru69917FxsYqMDBQsbGxuu+++3TkyJGzek4k6bbbblNQUJDH8bZixQpt375dN954o5o0aXLK/fz666968sknnd//Hhoaqq5du2rq1KkqLCx0WTcuLk6pqamSTlyRXvH7zvv27etx/2c6dsvKyjR79mxdfPHFioiIUHBwsDp06KC//OUvVZ4DJGnTpk364x//qBYtWigkJERdunTRc889d8rvrt+7d6/uv/9+nXvuuQoODlZoaKhiY2PVr18/Pffcc6d83gAAAACgvqAxDgAAAKDe+/TTT2W329WkSRNdf/31Z7y9aZpKSUnR8OHD9X//93+64IILNGTIEAUHB+utt97SBRdcoKVLl1a5/T//+U9de+21Kisr08CBAxUZGanPPvtMl19+uXbs2KFx48YpJSVFoaGhGjhwoBo3bqyPPvpIl19+uX799VeP+ywpKVG/fv300ksv6bzzznPWNWfOHCUnJ+vHH3902+b//b//p9dee00Wi0WXXHKJrrvuOkVEROi9997TxRdfrA8++KDKGn788UddcMEF+vzzz9WrVy9df/31atGixSmft40bNyo5OVlvvfWWgoKCdN111+maa65RdHS0/u///k8vvfSS2zZPPPGEBg4cqM8//1znnnuuhg4dqqioKL333nu66KKLNGfOnCofb9myZerVq5e2bNmiq666Sr1799a2bdv00EMP6a9//espc63sTI95+/btlZKSom7dukmSunXrppSUFKWkpGjo0KGnfbxzzjlHknTkyJEz/j7qsrIyDRs2TH/84x+Vnp6uc889VzfccINatmypBQsWKDk52eP4rK3xUFpaqqFDh+qmm27SF198ofj4eA0dOlSJiYnatWuXHn30UecHASr6+eefdeGFF+qDDz5Qz549ddVVV+no0aP6xz/+oauvvlqlpaVn9LyUa9asmf7whz9o69at+uabb1yWvfnmm5JOXFV+Kps2bVK3bt301FNP6cCBA7r00kvVv39/5ebm6oknntAll1yivLw85/pDhw7VJZdcIklKSEhwjoWUlBQNHDjQbf9nOnaLi4s1aNAg3X333crMzNQll1yiG264QcXFxXrllVeUlJSkdevWuW23cuVK9ezZU++//74iIiJ0ww03qHXr1powYYKGDRvmsfZ9+/YpOTlZL7/8soqLizVw4EBdf/31io+P1/r16zV16tRTPncAAAAAUG+YAAAAAFDP3XHHHaYk88orrzyr7WfNmmVKMlu0aGFmZmY64w6Hw3zyySdNSWaTJk3MAwcOuGzXtm1bU5IZFBRkfvnll854WVmZ+cc//tGUZHbp0sVs3ry5uX79eufygoIC8+KLLzYlmVOnTnXZ51dffWVKMiWZ7du3N3/66SfnsqKiIvOmm24yJZkXXXSRWx0fffSRefjwYY9xm81mNm/e3CwsLHRZVl6fJPP22283jx8/7rZ9dna2Kcls27atSzw1NdVjDaZpmoWFheaKFStcYl988YUpyQwODjb/85//uCx74403TElmQECAuXHjRpdlffr0ceY4e/Zsl2VpaWmmYRim1Wo1f/75Z7c8qnK2x7x82ZNPPlntxzJN07Tb7eYFF1zgrKNHjx7mY489Zn700UenzXvChAmmJLNXr17mzp07XZYtXrzYtFqt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Fi9erKysLLVr105///vf1apVq7Pevzecf/75ysrK0rPPPqtOnTopKytLixcv1urVqxUWFqaHHnpIH330kcs2gYGBWrZsma6//nrt2bNH77zzjt5880199tlnvzufoKAgLV26VK+++qq6deumr7/+Wh999JECAgJ033336YcfflD37t3dtuvTp49Wr16tIUOG6Ndff9VHH32kPXv26KmnntKiRYs8PtaDDz6oBx54QDExMVq3bp0WL16sdevWqXPnznrllVf07bffqlGjRr+7JgAAAADwNsOszhedAQAAAADqRHp6uq644gr16dPHeRtjAAAAAAAA/D5cMQ4AAAAAAAAAAAAA8Gs0xgEAAAAAAAAAAAAAfo3GOAAA9dzcuXNlGIaCg4P1yy+/uC3v27evunTp4vw9Li5OhmHIMAxZLBY1adJEXbt21V133aXVq1dX+TjHjx/Xiy++qF69eikiIkLBwcE699xzNWbMGG3bts1t/aysLKWmpio+Pl7BwcEKDw9XUlKSxo0bp507d9ZM8QAAAAAA+Kjy+bphGFq5cqXbctM0FRsbK8MwdN1117ktP3LkiIKDg2UYhjZv3uzxMUaOHOl8DMMw1LhxY3Xr1k3PP/+8iouLa7wmAADqM5u3EwAAADWjuLhY06dP1yuvvHLadZOSkvTggw9Kko4eParNmzdr8eLFev311/XXv/5VL7zwgsv6Bw8e1MCBA7V27Vpdd911uvXWWxUeHq6tW7fq3Xff1WuvvaaSkhLn+q+//rruvvtutWjRQrfddps6duyosrIybdy4UfPnz9eMGTNUVFQkq9Vas08CAPiBvn37yjRNb6cBAACAGhIcHKyFCxfq0ksvdYmvWLFCe/bsUVBQkMftFi9eLMMw1KpVKy1YsEBTp071uF5QUJDeeOMNSSea6R988IEeeughff/993r33XdrthgAAOoxGuMAAPiJpKQkvf766xo/frzatGlzynWjo6N1++23u8SeeeYZ3XrrrXrxxRfVoUMH3X333c5lI0eOVGZmpt5//33ddNNNLttNmTJFjz32mPP3jIwM3X333brkkkv06aefqlGjRi7rP//883r66afPtkwAAAAAAOqVa665RosXL9bLL78sm+3kW/ILFy5U9+7ddfDgQY/bvfPOO7rmmmvUtm1bLVy4sMrGuM1mc5nj33PPPerVq5cWLVqkF1544bTvEQAA0FBwK3UAAPzEhAkTZLfbNX369LPaPiQkRG+//baaNWump59+2nm14urVq/XZZ59p1KhRbk1x6cQn05977jnn75MnT5ZhGFqwYIFbU1w68Un5KVOmcLU4AAAAAKBBGD58uA4dOqTly5c7YyUlJXr//fd16623etxm9+7d+vrrr3XLLbfolltuUXZ2tjIyMqr1eBaLRX379pUk7dq16/emDwCA36AxDgCAn4iPj9eIESP0+uuvKycn56z2ER4erhtvvFG//PKLNm3aJEn6+OOPJUl33HHHabcvLCzUf//7X/Xt21cxMTFnlQMAAAAAAP4kLi5OvXv31r/+9S9n7IsvvlBeXp5uueUWj9v861//UlhYmK677jr17NlTCQkJWrBgQbUfc8eOHZKk5s2b/77kAQDwIzTGAQDwI4899pjKysr0zDPPnPU+unTpIunkJHrz5s2SpK5du5522+3bt6usrMy5j4oOHz6sgwcPOn8qfic5AAAAAAD+7NZbb9WSJUtUVFQkSVqwYIH69OlT5W3OFyxYoD/84Q8KCQmRJA0bNkzvvfeeysrKPK5fPtfesWOHpk2bpiVLligxMVHnnXde7RQEAEA9RGMcAAA/0q5dO91xxx167bXXtHfv3rPaR3h4uCTp6NGjkqT8/HxJ8nhb9MrK1y3fR+XcWrZs6fwpvxIdAAAAAAB/d/PNN6uoqEiffvqpjh49qk8//bTK26hnZWVpw4YNGj58uDM2fPhwHTx4UMuWLXNbv6CgwDnXbt++vSZMmKDevXvro48+qrV6AACoj2zeTgAAANSsxx9/XG+//bamT5+ul1566Yy3P3bsmKSTjfDGjRtLOtEob9KkySm3Ld+mfB8V/fvf/1Zpaal++OEHPfTQQ2ecFwAAAAAA9VXLli3Vv39/LVy4UIWFhbLb7Ro6dKjHdd955x2FhYWpXbt22r59uyQpODhYcXFxWrBgga699lqX9YODg/XJJ59IkoKCghQfH8/XmwEA4AGNcQAA/Ey7du10++2367XXXtOjjz56xttv3LhRktS+fXtJUseOHSVJGzZs0GWXXXbKbdu3by+bzebcR0V9+vSRJNlsvPwAAAAAADQ8t956q0aPHq19+/Zp0KBBHj98bpqm/vWvf6mgoECdO3d2W37gwAEdO3bM5U5tVqtV/fv3r83UAQDwC9xKHQAAP/T444+f1XeNHzt2TB999JFiY2PVqVMnSdLgwYMlnfjE+umEhYWpb9++WrFihX755ZczTxwAAAAAAD914403ymKx6Ntvv63yNuorVqzQnj179NRTT2nx4sUuP6+99poKCwu1ZMmSuk0cAAA/wSVbAAD4oYSEBN1+++365z//qbZt21brKu2ioiLdcccdOnz4sP72t7/JMAxJUu/evTVw4EC98cYbGjRokG644QaX7UpKSjRhwgQ999xzkqSJEyeqb9++uv322/XJJ5+4fd+4aZo1UyQAAAAAAPVIeHi4Zs2apV27djk/hF5Z+W3UH374YQUHB7st//vf/64FCxbo9ttvr+10AQDwOzTGAQDwU4899pjefvttbd26Veeff77Lsl9++cV5BfixY8e0adMmLV68WPv27dODDz6oP//5zy7rz58/X1dffbWGDBmiwYMHq1+/fgoLC9OPP/6od999V3v37nU2xi+77DL94x//0H333acOHTrotttuU8eOHVVSUqJt27ZpwYIFCgwMVKtWrermiQAAAAAAwEekpKRUuay4uFgffPCBrrrqKo9NcUm6/vrr9dJLL+nAgQOKjIysrTQBAPBLNMYBAPBT7du31+2336558+a5LVu/fr3uuOMOGYahRo0aKTY2VoMHD9af/vQn9ezZ0239li1bKiMjQ6+++qoWLVqkxx57TCUlJWrbtq2uv/563X///S7r33333erdu7defPFFZ8M9ICBACQkJSklJ0d13362EhIRaqx0AAAAAgPrms88+05EjR6q8mlw68XVnzz//vN5991395S9/qcPsAACo/wyT+5kCAAAAAAAAAAAAAPyYxdsJAAAAAAAAAAAAAABQm2iMAwAAAAAAAAAAAAD8Go1xAAAAAAAAAAAAAIBfozEOAAAAAAAAAAAAAPBrNMYBAAAAAAAAAAAAAH7N5u0E6prD4VBOTo4aNWokwzC8nQ4AAAAAoJ4zTVNHjx5VmzZtZLHw+fNTYU4OAAAAAKhJZzInb3CN8ZycHMXGxno7DQAAAACAn/n5558VExPj7TR8GnNyAAAAAEBtqM6cvME1xhs1aiTpxJPTuHFjL2cDAAAAAKjv8vPzFRsb65xvomrMyQEAAAAANelM5uQNrjFefqu2xo0bMwkHAAAAANQYbg1+eszJAQAAAAC1oTpzcr78DAAAAAAAAAAAAADg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jRs3atCgQQoPD1dUVJTuuOMOHTx4UJKUnp6uwMBAff311871n332WUVGRjq/M7tv37564IEHnMuLi4v1yCOPKDY2VkFBQWrfvr3efPNNSZLdbteoUaMUHx+vkJAQnXfeeXrppZfqrlgvGjNmjH766ScVFxdr9erV6tWrl3NZenq65s6d6/x96tSp+vHHH1VUVKTDhw8rIyPD2RSXpJCQEC1btkwHDhxQSUmJdu3apddee83ZaAcAAAAA1A8NdU5OYxwAAAAAUKeOHDmiK6+8UhdccIHWrFmjpUuXav/+/br55pslnZxg33HHHcrLy1NmZqaeeOIJvfHGG1U2YUeMGKF//etfevnll7V582b985//VHh4uKQT35MdExOjxYsXa9OmTZo4caImTJig9957r85qBgAAAADAFzTkOTm3UgcAAAAA1Kl//OMfuuCCC/S3v/3NGZszZ45iY2O1bds2nXvuuZo6daqWL1+uu+66Sxs3blRKSoquv/56j/vbtm2b3nvvPS1fvlz9+/eXJLVr1865PCAgQJMnT3b+Hh8fr1WrVum9995zTvwBAAAAAGgIGvKcnMY4AAAAAKBO/fDDD/rqq6+cnx6vaMeOHTr33HMVGBioBQsWKDExUW3bttWLL75Y5f7Wr18vq9WqPn36VLnOzJkzNWfOHO3evVtFRUUqKSlRUlJSTZQDAAAAAEC90ZDn5DTGAQAAAAB16tixYxo8eLCeeeYZt2WtW7d2/ndGRoYk6fDhwzp8+LDCwsI87i8kJOSUj/fuu+/qoYce0vPPP6/evXurUaNG+vvf/67Vq1f/jioAAAAAAKh/GvKcnMY4AAAAAKBOXXjhhfrggw8UFxcnm83ztHTHjh3661//qtdff12LFi1SSkqKvvzyS1ksFrd1u3btKofDoRUrVjhv21bRN998o4svvlj33HOPy/4BAAAAAGhoGvKc3D17L5g5c6bi4uIUHBysXr166bvvvqty3blz58owDJef4ODgOswWAAAAAFBdeXl5Wr9+vcvPXXfdpcOHD2v48OH6/vvvtWPHDi1btkypqamy2+2y2+26/fbbNWDAAKWmpuqtt95SVlaWnn/+eY+PERcXp5SUFN15551asmSJsrOzlZ6ervfee0+S1KFDB61Zs0bLli3Ttm3b9MQTT+j777+vy6cBAAAAAIA6x5zcldevGF+0aJHG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AAAAAAAAAAAAgIBGYRwAAAAAAAAAAAAAENAojAMAAAAAAAAAAAAAAhqFcQAAAAAAAAAAAABAQKMwDgAAAAAAAAAAAAAIaBTGAQAAAAAAAAAAAAABjcI4AAAAAAAAAAAAACCgURgHAAAAAAAAAAAAAAQ0CuMAAAAAAAAAAAAAgIBGYRwAAAAAAAAAAAAAENAojAMAAAAAAAAAAAAAAhqFcQAAAAAAAAAAAABAQKMwDgAAAAAAAAAAAAAIaBTGAQAAAAAAAAAAAAABjcI4AAAAAAAAAAAAACCgURgHAAAAAAAAAAAAAAQ0CuMAAAAAAAAAAAAAgIBGYRwAAAAAAAAAAAAAENAojAMAAAAAAAAAAAAAAhqFcQAAAAAAAAAAAABAQKMwDgAAAAAAAAAAAAAIaBTGAQAAAAAAAAAAAAABjcI4AAAAAAAAAAAAACCgURgHAAAAAAAAAAAAAAQ0CuMAAAAAAAAAAAAAgIBGYRwAAAAAAAAAAAAAENAojAMAAAAAAAAAAAAAAhqFcQAAAAAAAAAAAABAQKMwDgAAAAAAAAAAAAAIaBTGAQAAAAAAAAAAAAABjcI4AAAAAAAAAAAAACCgURgHAAAAAAAAAAAAAAQ0CuMAAAAAAAAAAAAAgIBGYRwAAAAAAAAAAAAAENAojAMAAAAAAAAAAAAAAhqFcQAAAAAAAAAAAABAQKMwDgAAAAAAAAAAAAAIaBTGAQAAAAAAAAAAAAABjcI4AAAAAAAAAAAAACCgURgHAAAAAAAAAAAAAAQ0CuMAAAAAAAAAAAAAgIBGYRwAAAAAAAAAAAAAENAojAMAAAAAAAAAAAAAAhqFcQAAAAAAAAAAAABAQKMwDgAAAAAAAAAAAAAIaBTGAQAAAAAAAAAAAAABjcI4AAAAAAAAAAAAACCgURgHAAAAAAAAAAAAAAQ0CuMAAAAAAAAAAAAAgIBGYRwAAAAAAAAAAAAAENAojAMAAAAAAAAAAAAAAhqFcQAAAAAAAAAAAABAQKMwDgAAAAAAAAAAAAAIaBTGAQAAAAAAAAAAAAABjcI4AAAAAAAAAAAAACCgURgHAAAAAAAAAAAAAAQ0CuMAAAAAAAAAAAAAgIBGYRwAAAAAAAAAAAAAENAojAMAAAAAAAAAAAAAAhqFcQAAAAAAAAAAAABAQKMwDgAAAAAAAAAAAAAIaBTGAQAAAAAAAAAA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tTLG6NFHH1V2drYkrslRvLS0NO3Zs0cpKSmScnLF4XDonnvu0dy5c/XAAw9ozZo19EUoVr9+/fTQQw8pOjpakvTBBx9owoQJGj58uP785z/rmmuuUWxsrPbu3evjluLXYDUFl2zy5MkaP368QkNDNWTIEE2YMKHI4nhaWpqvmwo/1r59ex05ckTvv/++53YkktS6dWv169dP8fHxnskMUFBuUWDkyJH64Ycf9PDDD0vK+dCF0+lUaGio/vnPf+rrr7/WqlWrfNlU+LHw8HA98MAD6tq1qyTps88+0/jx4/X444/r3Xff1caNG1WpUiXPbl8uoFAUY4wqVKigCRMm6O2331Z8fLwkeb7GoUuXLpo0aZLWr1+vlJQUFnNQSG7R4bPPPlNMTIw6duyo7777Tu+8847+/ve/61//+peWL1+u48ePa8aMGT5uLQBfa9Gihe6++24NGjRIdevW1QsvvFCoOJ471uQWEoCidOnSRQkJCfroo4+84j179tR1112n//3vf2x8QLGysrIkSX/961/Vt29fRUREaN68ebr66qtVvXp12Ww2vfTSS0pJSdG7777r28bCr1199dXKysrSokWLJElhYWHKyspSpUqVtGbNGn399deaN2+eJK7JUVjunCcmJkbDhg3T008/rW+//dZzPW6M0d13362hQ4dq+fLlysrK4pocheTOmTt27CiHw6GMjAzt379fy5Yt09y5czV48GC99NJLqlSpkt58800ftxa/BoVxXJTcBTu32y1jjMLCwuR0OhUUFKThw4drwoQJ+vHHHzVy5EglJyfr+eefV58+fdipCUk5n/5ct26d4uPjtWvXLknS3XffrbZt2+r+++/X2rVrvXaHd+3aVaGhoUpKSvJVk+GH0tLStGTJEs2cOVMbN27UwYMHVb16db322mt66623NGHCBEk5xXEp57a0zZs3V9WqVX3ZbPih/DtfwsLCZLfbJeUUyl999VXdf//9at68uerUqaOuXbvqzJkz7JZBkfJ/VUOvXr1Uu3ZtLVy4UJs3b5aUs3DjcDhUr1497d+/X263m8UceHG73bLZbJ6vBFm/fr3GjBmjIUOGqGnTpp5Fm3bt2ql+/fqeO1gAKJ9yF+2uv/56BQcHS5Kio6O1cOFCT3F87969sixLixcv1vLlyz39C8q3zMxM7dy5U3v37tUPP/wgy7L05z//WS6XS1OmTNH27du9iuC9e/dWYmKiEhMTfdhq+LPcPkiSHnvsMc2YMUOtWrXyOubUqVOqWbOmGjZseLmbBz+XO8d1u92qWbOmnnjiCS1atEj//Oc/JeXkV1ZWlqpXr67u3bt73ZkLkHLuGJmSkqKTJ096YkOGDJHT6dRzzz2no0ePyrIsWZalypUrKyoqSnv27JHD4eCaHIXk3kUyV1hYmP74xz9qxIgRknLy7cyZM2rUqJHatGnjiyailDh83QD8tiQmJuqKK66Q0+lUxYoVJeUUn1wul+x2u4YPHy7LsvTiiy+qTZs2+u677/TSSy8pLCzMxy2Hr6WmpqpTp04KCgrSoUOHVLNmTfXr10/z58/X8uXLNWDAAE2YMEEPPfSQhgwZotq1a2vdunWSpIiICB+3Hv4iNTVV7dq1U0REhM6cOaOlS5cqKipKf/vb33TLLbdoyZIluvvuu3Xq1CnFxsYqOjpa//vf/3T06FHVrFnT182HnylqTJOka665xvN3Y4wsy1J2drZatWrl+aQxF1A4d+6cZs2apalTpyoiIkJOp1MOh0Pt2rXTxIkT9cQTT2jOnDkaO3as+vbtKylnMbpu3brsukIhRfVHL7/8ss6cOSMp58MVbrfb83VGTZo0kST6I6CcKrhol/vhmqioKC1cuFDjx49Xt27dNGLECM2dO1dxcXGeD42i/EpJSdHNN9+sjIwMnTx5UlFRUZo8ebJGjBih9evXq3379po4caImT56sQYMGSZK+/PJLVatWjTUdeGRmZuqjjz5SfHy8Tp06peTkZA0ZMkRNmjRRx44ddcsttxR6zqeffqrQ0FDVrl3bBy2GP0pPT9fp06dVr149zxgmSX369NG+ffs0d+5cuVwuTZw40fPhi7CwMM/fmQNDyhnXbr/9diUmJur8+fO64YYb9Pjjj2vAgAH67rvv9PLLLys7O1v333+/mjZtKilnjTkqKkoZGRkKDw8nj8q54sa05s2bq23btpK8PwDmcDgUFxeno0eP6qqrrvJVs1EKLMM9I3AB6enpevHFF/XJJ5/owIEDqly5slJSUvTQQw+pffv2noEl/06XO+64Q2+//bbee+899e/fnwlLOedyudS3b18FBwdr6dKl+u677/T5558rNjZWPXr00DvvvCNJ+uMf/6ht27bp6NGjatWqlbZt26bFixfr//7v/3x8BvAHxhhNmDBBhw4d0sqVK1W5cmWtXr1ar7/+uv73v//p9ddfV7du3bR161aNHj1aWVlZcrlccjqdeuaZZzRs2DBfnwL8QEnHtPyWLl2q2NhYrVy5UjfffLMPWg1/k56erhtvvFE7duzQbbfdpiVLlqhy5crKzs72FCs++OAD/etf/9Inn3yi1q1bq2rVqoqLi9Orr76qIUOG+PgM4A9+qT9q06aNmjdvXug5S5cu1eTJk/Xuu+/q2muv9UGrAfhCSRbtcj+sLkk//PCDbrzxRh0+fFgrVqzQ7bffzjV5OZedna2bbrpJkZGRevrpp7V3717973//0/z58/XYY49p2rRpOnPmjAYPHqyzZ88qLS1N11xzjd5//33mLvA4d+6cbr/9dgUFBalSpUrq1q2bfvrpJ3322Wcyxqh///66++67PccnJCTok08+0eTJk/Xqq69q8ODBPmw9/EVaWpqaN2+uU6dO6csvv1SzZs28xrADBw7opZde0gsvvKChQ4eqffv2Onv2rKZNm6a4uLgiP3yB8uf8+fPq2LGjmjZtqkGDBiktLU3Tpk1TZGSk5s2bp65du+rFF1/U8uXLdfjwYd16663Kzs7WK6+8ohUrVui2227z9SnAxy40pg0YMEBjxozxHP/VV1/pk08+0f33369ly5bp9ttv92Hr8WtRGMcvSk1NVe/evVW7dm21b99eo0aN0okTJ7R37169//77ql+/vkaOHKkWLVpIyilcvfLKKxo7dqxWrlypwYMHe26Lw0V4+XX+/Hl169ZNEydO1PDhwz3xTz75RAMHDlT37t0938vx+eefKyEhQQ6HQ82aNVPHjh1ZxIGknNvV9O/fXy1atNDTTz/tie/Zs0dPPfWUPv74Y73xxhu69tprlZaWpt27dyszM1M1a9ZUs2bN6ItQojFt1KhR+t3vficpZyFnxYoVWrBggRYtWsSHdCApp/DwwAMP6KuvvlL37t0VFxenatWq6bXXXitUHD906JB27dqllStXqmHDhurSpYt69OjBuIaL7o927dql5cuX64UXXtDLL79MfwSUIxezaJc7vsybN08PPPCA1wfVJebB5VlSUpJuueUWPfvss7rpppsk5VxfvfTSS7r33nv1xBNP6MEHH1Rqaqo2btyojz/+WNWrV1eHDh100003MXeB0tLS1KVLF9WvX19z585VgwYNtHr1anXs2FGhoaFatWqVli1bpocffljXX3+9zp49q/nz52vp0qWaN2+eBg4cSB5B2dnZ+v3vf6+DBw8qLCxMCQkJ2rBhg6666iqv4viZM2e0adMmTZs2TVLObvH7779fgwYNIo8gSfrss880ZswYrVu3TvXr15eU00/16NFDGRkZev7553Xddddpy5YtWr9+veLj4xUTE6MhQ4aob9++5FE5d7FjWnJyshYsWKDXX39djz/+uG677TZy6LfOAMVIT0831157rbntttvMmTNnjDHG/Pe//zX//Oc/jTHG7Nq1y4waNcosXLjQGGOM2+02xhgza9Ys884773hiuXGUX+fOnTO1a9c2jz32mCeWmxfr16834eHhZtasWcU+nxxCrvHjx5tbbrnFpKSkeMV37txp+vfvb+644w6TnJzso9bBn13smJaenm7i4uLM3XffbVavXm2MYUxDnjlz5ph58+aZjIwMs3z5ctO5c2fTv39/c/bsWWOMMVlZWcU+lzzCxfZHaWlp5p133jHDhw83cXFxxhjmRkB5ce7cOdO2bVszaNAgc+jQIWOMMatWrTJJSUkmNTXVvPHGG6Z3797mk08+8TznyJEjpk+fPmb58uXGGMYd5Dh8+LAJCgoy7733njHGexx59tlnjc1m84wxRSGHyjen02n+9Kc/mQEDBpjU1FRjjDFxcXHm5ptvNiNHjjT79+83xhjzhz/8wSxdutTzvFOnTpl9+/YZY+iLkOOrr74yY8aMMW+88YY5evSo6d+/v6levbrZs2ePMcaY7Oxsr+PPnz9vzp8/77nOIo+Qa/369aZ27drmu+++M8bkXGMZY0xKSopp27at6dChg1eu5M8t8qh8u9Qx7ccffzTffvutMYYcCgQ2Xxfm4b9efPFFVa1aVS+99JKqVq2qxYsXa/r06Zo5c6aWLVumli1bqnfv3nr22WeVkZEht9stSXrkkUc8nwSV+FR6eWeMUYUKFTRhwgS9/fbbio+Pl5STF8YYdenSRZMmTdKGDRuUnJzsyZv8yCHkat++vY4cOaL3339fmZmZnnjr1q3Vr18//e9//1N6eroPWwh/dTFjWnp6usLCwjy7avr06cOYBi+TJ0/W+PHjFRoaqiFDhmjChAk6ffq0RowYoeTkZAUFBcnpdOrcuXOFnmtZFnlUzl1sfxQeHq4+ffrohRdeUL9+/YqcKwEIPC6XSw899JCioqK0dOlSNWjQQKtWrdK8efMUGxurEydOaNiwYapbt64OHTrkeV79+vW1ePFiDR8+nPkLPDkQExOjYcOG6emnn9a3337ruR43xujuu+/W0KFD9dZbbykzM9OztpMfOVS+ZWdn6+DBgxo5cqQqVqyo0aNH6x//+Icsy9LevXs1c+ZMff/996pbt652797teV6NGjV05ZVXSmIOjBwtWrTQ3XffrUGDBqlu3bp64YUX1KlTJ3Xp0kVff/21HA6Hpw/KyMhQSEiIQkJCVLlyZUnkEfJcffXVysrK0qJFiyTl3FUgKytLlSpV0po1a/TNN9/oqaee8hzvcDg8fyePyrdLHdOuuOIKNW7cWBI5FAgojKNYud+JWb16dY0aNUr/+te/NGzYMHXp0kXz58/X8uXLVbt2bXXq1ElhYWGe293kooOAy+Xy5ECvXr1Uu3ZtLVy4UJs3b5aUkyMOh0P16tXT/v37uQUJvJw/f17r1q1TfHy8du3aJUm6++671bZtW91///1au3atVxG8a9euCgkJUVJSkq+aDD92MWNaeHi4JCk4OJgLcHjkLtC43W4ZYxQWFian06mgoCANHz5cEyZM0I8//qiRI0d6brPVt29fZWRk+Ljl8DeX0h+FhISoSpUqkuiPgPLiYhbt9uzZIymvCBoZGSmJ/qI8czqdSklJ0cmTJz2xIUOGyOl06rnnntPRo0c9+VG5cmVFRUVpz549CgoKks3GUiG8xcfHKyEhQT179tT69eu1ceNGLViwQOvXr9czzzyjn376SbNmzdKHH37ouaUxUFB2drYk6frrr1dwcLAkKTo6WgsXLvQUx/fu3SubzabFixfrrbfektPplMSHc5Ajd57jdrtVs2ZNPfHEE1q0aJH++c9/SspZw8nKylL16tXVvXt3ffvtt75sLvwUYxokCuMoRlJSkr755hvdddddyszM1P79+/X444/rvvvu0/Lly9W1a1dNmTJF48ePZ8EXXs6dO6cpU6YoOTlZdrvdM4lt166dJk6cqO+//15z5szR6tWrPc/JzMxU3bp15XK5fNVs+JnU1FS1bdtWkydP1sCBAzV48GBNmjRJkrR8+XJ16NBBEyZM0Msvv6wTJ05IktatWydJioiI8FWz4acY01AaEhMTdf78eaWnp3sWZhwOh+e78IYPH64//elPOnv2rNq0aaP7779fd911l8LCwnzccvgT+iMAJXUxi3b16tWTROEAOVJSUtS3b1/dcMMN6tKli8aOHauTJ09qwIABuuOOO/Tpp5/q8ccf1/79+z3PiYiIUFRUlDIyMrgzCQqx2+1q2bKlKlWqpLS0NNWsWVO1a9eWJN14442KiYnR2rVrZVmWxo0b55VbQK6goCCvn3M/eBwVFeUpjnfr1k0PPvigxo4dq+rVq3vt8kX5lZ6e7vlAl9vt9nyAq0+fPhoxYoTmzp2r559/XpI8H7oICwvz/J1xDfkxpkGiMI5iGGOUnJysc+fO6eTJk9q7d69SUlI8v7/nnntUqVIlde3aVUuWLNFHH33kdVtjlE/p6em66aabNGfOHI0ZM0YpKSlyOByeT4UOGDBA06ZNk2VZuuuuu9SjRw/93//9nx566CFNmjRJ1apV8/EZwB+4XC7dfvvtatSokT766CNt3LhRDz30kF5++WUNGjRIkvT++++rb9++Wrx4sVq0aKGbb75ZDz74oObMmeNZGARyMabhUqWnp+vZZ5/VoEGD1KtXL3Xv3l3XXnutXn/9dc/Fkd1ul9vtlt1u19ChQ1WrVi0dPnxY//nPfzRmzBguwuGF/ghASbFoh0tx/vx53XDDDapcubKmTJmiyZMn64MPPlCvXr300Ucf6d5779U999yjffv2qXv37rr33ns1fvx4zZw5U3fffbcqVKjAByxQSIUKFXTmzBllZmaqRo0aSkhI0JYtWzy/z/1KodWrV+v555/X66+/7sPWwl9kZmZqzZo1mjx5skaPHq3bbrtNr732mrZv3y5Jstlsng0yucXxsLAwzZ07VytWrFDfvn25loLS0tLUrFkzNW3aVPv27fPKm+joaE2YMEFDhgzR1KlTNXbsWL344ot66qmn9NZbb2ngwIGS+OAgvDGmQZL42BWKFB4eroYNG8pms6levXr6wx/+oLlz56p27drq0KGDZs2apebNm2vOnDlav369nn76af33v//1dbPhQy6XS4888oiqVKmiJ554QnFxcRoxYoRee+01Va5cWdnZ2QoKClKfPn3UrFkz7dq1SytXrlTDhg31/vvvq0ePHtxKHZJybq+VmpqqiRMnqmrVqqpatapat26tZs2aaeDAgRo2bJjefPNNvfjii/r888+VkJAgh8Oh2bNnq2PHjuQRCmFMw6VITU1V7969Pbe0fuGFF3TixAnt3btX77//vhISEjRy5Ei1aNFCNptNxhgtW7ZMb7/9tlauXKn+/fuzkINC6I8AlFRxi3bdunWTlLdoN3nyZD3//PNKTk7WjBkzfNxq+Nr27duVkZGhuXPnem7/OXz4cPXo0UOxsbF6/vnn9cc//lGtWrXS+vXrFR8fr5iYGL3zzjueIhTXUuXb+fPntWPHDp06dUrdu3dXeHi46tSpo+zsbB09elTXXnutnnrqKfXs2VPDhg3T119/raSkJL300kuqWLGiEhIS1K5dO1+fBnzs3Llzuv322xUUFKRKlSqpW7du+umnn/TOO+/IGKMBAwZozJgxstvtnn5nxYoVOnz4sN577z2upSApZ33wnnvuUd26ddW0aVPdeOON2rBhg6666irPndsaN26shx56SDfccIOmTZumHTt2KCwsTG+88YZuueUWxrVyjjENxaEwDmVmZmrbtm1KT0/XDTfcoPDwcFWsWFFXXnmlpk+frpUrV+q+++5Tdna2rr/+el155ZVKTEzUzp07VbFiRW3ZskWNGzfme6jKObvdrjp16qhevXq65557VL9+ff3jH//QiBEj9OqrryoiIsJTHG/YsKEaNmzo+eSexG1tkMflcunw4cNeu16MMbrhhhu0YsUKDRgwQI8//rgeeeQRtW/fXu3bt/dha+FvGNNQGjIyMtSrVy/VrFlTixYtUtWqVbVu3TodPHhQ48ePV4sWLfTMM8/os88+U4sWLTwX2ydOnNC///1vDRw40DOucRFeftEfASgpFu1QWs6fP69z58555h8ZGRmqUKGC1q5dq65duyo2NlZbtmxRp06d1KlTJ02ZMsVzq2KuyZGSkqJevXopMTFRR44c0VVXXaXnnntO3bp1U6dOnTRy5Eh9+OGHuu+++1S/fn1t375dkZGRmjJliipWrKh58+YpLi5O06ZN8/WpwIfS0tJ00003qX79+po7d64aNGig1atXa8CAAfrjH/+oVatWadmyZWrSpImuv/56WZal7777TvHx8Xr99de9iuJcS5Vv33zzjRwOh+69915dd911+tOf/qQuXbro448/1lVXXSWn0ymHw6ErrrhC/fr1U48ePSTljIURERGMa+UcYxp+kUG5lpKSYnr27GluvfVWM2jQIJOWlub53d69e83IkSPNwoULTXZ2tjHGmP/973/m448/NufPnzfGGPOPf/zDBAcHmx07dvik/fA/6enpxhhjsrKyzKuvvmo6d+5s+vXrZ86ePWuMMSY7O9ukpqb6sonwY2632xhjzMyZM02LFi3M+vXrvX6XnZ1tHn74YdO9e3dz9uxZz/GAMYxpKD3PPvus6du3r0lKSjLGGPPyyy+bzp07mzp16pilS5caY4x54403zJVXXmnS09ON0+n0er7b7aZ/KufojwCUVHJysuncubNp0KCBsSzL/O53v/PMge+55x7TsWNHc+bMGWOMMe+++67561//amJjY82pU6eMMcY888wz5oorrjAHDx702TnAf5w8edJUq1bNPPLII55YZmamMcaYpKQkExERYWbPnu2r5sGPJScnm3r16pnhw4ebrVu3mo0bN5qOHTuaZs2amczMTJORkWHGjx9vevXqZU6fPl3o+bNmzTIhISHmgw8+8EHr4S+cTqf505/+ZAYMGOBZ+4uLizM333yzGTlypNm/f78xxpg//OEPnuuqXImJicYYrqXg7ZNPPvGMY99//73p16+fqV69utmzZ48xxhiXy2WMyVuPNsaQP2BMwwVZxvDRmfIqNTVVbdu2VceOHfXEE0+oevXqCgsL0+7du+VyudSqVSstW7ZMGzduVKVKlTR9+nRVrlxZNptNu3fv1muvvaZnn31Wb7/9tvr37+/r04GPuN1u2Ww2ud1uWZYly7I8n9hzuVx644039MILL6h69ep69dVXtWTJEr3zzjtas2aNwsLCfN18+JHc2yBJ0hdffKGHH35YERERio2NVefOnT3Hvfjii3riiSe0a9cuValSxUethb9hTENpGjx4sJo3b65Zs2Zp1KhROnDggIYNG6YtW7Zo3759euCBBxQVFaVXXnlFS5Ys8XVz4WfojwCUVEpKiq6++mpdd911mjRpkjIzMzV58mQlJydr165dcrvd+stf/qIjR47otddeU7Vq1bye//jjj2vmzJn6z3/+o969e/voLOBr5uc71+Remy9atEiPPvqoZsyYoXvuuUeSlJWVpeDgYA0ZMkQRERF6+eWXfdxq+JPz58+rYcOGatOmjVatWuWJr127Vn369NH69evVtWtXnTx5Un/961+1YcMG3XTTTYqMjFRCQoKCg4O1detWLVu2TDfddJPvTgQ+d/78eQ0cOFC///3vNWTIEI0ePVqJiYlyuVxKTk5W8+bN9fjjj2vp0qVKTU3VU089xa2uUaTcu44W9MMPP2j8+PHasmWLNm7cqObNm2vx4sWy2+268847PXdBQfnFmIaSoKcop7KysjR8+HBdddVV+te//qWQkBBJ0n/+8x/deeeduuWWWzR79myNHDlSMTExevHFF9WhQweFh4dLkkJDQxUWFqZPP/2U2xiXc4mJibriiivkdDpVsWJFSfIUxe12u4YPHy7LsvTiiy+qTZs2+u677/TSSy9RFIeknO+dmjVrlqZOnaqIiAjPhyratWuniRMn6oknntCcOXM0duxY9e3bV1LOrWnr1q0rl8vl49bDXzCmoTQlJSXpm2++0VNPPaXMzEzt379fs2fPVteuXXXffffp/vvv15QpU1ShQgW1bNnS182Fn6E/AlBS58+fV7NmzdSmTRstX77cE58xY4b69Omjzz77TF27dtVjjz2mv/71r+rcuXORi3Zr1qxh0a6cSk9P1+nTp1WvXj1PUVyS+vTpo3379mnu3LlyuVyaOHGigoODJUlhYWGev1OMQq4zZ87IsiylpaXp1KlTuuKKK+RwOFSjRg1VrlzZs34TGRmpRYsWadWqVfrhhx+0f/9+NWrUSH379tW8efNUt25dH58JfC0+Pl4JCQnq2bOn1q9fr40bN2rdunVq3LixNm7cqKefflqzZs3S7t27dccdd0jidukoWsGieO44FxUVpYULF2r8+PHq1q2bRowYoblz5youLo6iOCQxpqFk6C3KqSNHjui7777T008/7bko+uCDDzR48GD95S9/0apVqzR9+nT99a9/1Y033qgbb7xRO3bsUEZGhn766Se1adNGlSpVUqVKlXx8JvCF9PR0vfjii/rkk0904MABVa5cWSkpKXrooYfUvn17NW3aVHa7XW63W3a7XUOHDtV7772nTz/9VO+9957n+4KY/JZv6enpuummm7Rjxw7t379fS5YsUeXKlT2fCh0wYIAcDof+9a9/6a677lLr1q1VtWpVxcXF6dVXXy20YwblF2MaSpMxRsnJyTp37pxOnjypvXv3KiUlxfP7e+65R2vWrFGXLl30zDPP6KOPPtK1117rKYCifKM/AlBSLNrh10hLS1Pz5s116tQpffnll2rWrJnnw+nR0dGaMGGCgoKCNHXqVH355Zdq3769zp49q7feektxcXGSKEYhT506dfTZZ5+pR48eGjhwoNavXy+73a4xY8bo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xpk8YxwAAAAAAAAAAAAA4NRojAMAAAAAAAAAAAAAnBqNcQAAAAAAAAAAAACAU6MxDgAAAAAAAAAAAABwajTGAQAAAAAAAAAAAABOjcY4AAAAAAAAAAAAAMCp0RgHAAAAAAAAAAAAADg1GuMAAAAAAAAAAAAAAKdGYxwAAAAAAAAAAAAA4NRojAMAAAAAAAAAAAAAnBqNcQAAAAAAAAAAAACAU6MxDgAAAAAAAAAAAABwajTGAQAAAAAAAAAAAABOjcY4AAAAAAAAAAAAAMCp0RgHAAAAAAAAAAAAADg1GuMAAAAAAAAAAAAAAKdGYxwAAAAAAAAAAAAA4NRojAMAAAAAAAAAAAAAnBqNcQAAAAAAAAAAAACAU6MxDgAAAAAAAAAAAABwajTGAQAAAAAAAAAAAABOjcY4AAAAAAAAAAAAAMCp0RgHAAAAAAAAAAAAADg1GuMAAAAAAAAAAAAAAKdGYxwAAAAAAAAAAAAA4NRojAMAAAAAAAAAAAAAnBqNcQAAAAAAAAAAAACAU6MxDgAAAAAAAAAAAABwajTGAQAAAAAAAAAAAABOjcY4AAAAAAAAAAAAAMCp0RgHAAAAAAAAAAAAADg1GuMAAAAAAAAAAAAAAKdGYxwAAAAAAAAAAAAA4NRojAMAAAAAAAAAAAAAnBqNcQAAAAAAAAAAAACAU6MxDgAAAAAAAAAAAABwajTGAQAAAAAAAAAAAABOjcY4AAAAAAAAAAAAAMCp0RgHAAAAAAAAAAAAADg1GuMAAAAAAAAAAAAAAKdGYxwAAAAAAAAAAAAA4NRojAMAAAAAAAAAAAAAnBqNcQAAAAAAAAAAAACAU6MxDgAAAAAAAAAAAABwajTGAQAAAAAAAAAAAABOjcY4AAAAAAAAAAAAAMCp0RgHAAAAAAAAAAAAADg1GuMAAAAAAAAAAAAAAKdGYxwAAAAAAAAAAAAA4NRojAMAAAAAAAAAAAAAnBqNcQAAAAAAAAAAAACAU6MxDgAAAAAAAAAAAABwajTGAQAAAAAAAAAAAABOjcY4AAAAAAAAAAAAAMCp0RgHAAAAAAAAAAAAADg1GuMAAAAAAAAAAAAAAKdGYxwAAAAAAAAAAAAA4NRojAMAAAAAAAAAAAAAnBqNcQAAAAAAAAAAAACAU6MxDgAAAAAAAAAAAABwajTGAQAAAAAAAAAAAABOjcY4AAAA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ZjAOAAAAAAAAQF0zGAcAAAAAAACgrhmMAwAAAAAAAFDXDMYBAAAAAAAAqGsNf8yVm5qasmjRoowfPz4NDX/UTQHQh407/YbeTqGDxwb0dgYAAD3L8TYAAAB0r806Y3z16tX5xCc+kUGDBuXtb397Hn/88STJpz/96VxwwQXdmiAAAABsLRxvAwAAQM/YrMH4GWeckXvvvTe33HJLBgxoO23v0EMPzaxZs7otOQAAANiaON4GAACAnrFZ78d23XXXZdasWdl///1TKpVq8be//e155JFHui05AAAA2Jo43gYAAICesVlnjC9btiwjRozoFF+1alWHA3cAAABg4zneBgAAgJ6xWWeMT548OTfccEM+/elPJ0nt4Pw73/lODjjggO7LDgAAALYijrcBAAC2XntdvVdvp9DBfSfd19spdKvNGoz/0z/9U4444oj83//9X1paWvL1r389//d//5fbbrstv/nNb7o7RwAAANgqON4GAACAnrFZb6V+0EEH5d57701LS0v22muv/PKXv8yIESMyZ86c7Lvvvt2dIwAAAGwVHG8DAABAz9jkM8abm5vzV3/1V/niF7+YK6+8sidyAgAAgK2O420AAADoOZt8xni/fv3yH//xHz2RCwAAAGy1HG8DAABAz9mst1I/9thjc91113VzKgAAALB1c7wNAAAAPWOT30o9SSZMmJDzzjsvv/3tb7Pvvvtm8ODBHb7/mc98pluSAwAAgK2J420AAADoGZs1GP/ud7+b7bffPnfffXfuvvvuDt8rlUoO1AEAAGAzON4GAACAnrFZg/FFixZ1dx4AAACw1XO8DQAAAD1jsz5jvL2iKFIURXfkAgAAALzK8TYAAAB0n80ejH//+9/PXnvtlYEDB2bgwIGZOHFifvCDH3RnbgAAALDVcbwNAAAA3W+z3kr94osvzhe/+MWccsopOfDAA5Mk//u//5u//uu/zrPPPpu/+7u/69YkAQAAYGvgeBsAAAB6xmadMf7Nb34zl112Wb7yla/k6KOPztFHH50LL7ww3/72t/ONb3yju3MEAACArUJ3H29feumlGTduXAYMGJD99tsvd9xxxwa3vfLKK/Oud70rQ4cOzdChQ3PooYd22r4oipx99tnZcccdM3DgwBx66KF5+OGHNzkvAAAAeKNt1mD8qaeeyjvf+c5O8Xe+85156qmn/uikAAAAYGvUncfbs2bNyowZMzJz5szcc889mTRpUg477LA888wzXW5/yy235KMf/Wh+/etfZ86cORk7dmze97735cknn6xtc+GFF+Yb3/hGLr/88tx+++0ZPHhwDjvssLzyyiubVigAAAC8wTbrrdR32223/PjHP86ZZ57ZIT5r1qxMmDChWxIDAACArU13Hm9ffPHFOfnkkzN9+vQkyeWXX54bbrghV111VU4//fRO2//7v/97h6+/853v5D/+4z8ye/bsnHjiiSmKIpdccknOOuusHHPMMUnWfh76yJEjc9111+XP//zPO93mmjVrsmbNmtrXK1asSJK0tLSkpaUlSVIul1Mul1OtVlOtVmvbrou3tramKIrXjVcqlZRKpdrtto8nSWtr60bFGxoaUhRFh3ipVEqlUumU44bialKTmtSkJjWpSU31VlO/ctttF0XSUpRSTpFKu9Mva/FSkUqpLV4tktailEqpSLldvLVIqkUpDaUipfbxalJN53hLNSlSSr9ykZZSY1vuRXOSIq3tYmvjTUlKaS3161hT0ZRivXgpRSpFc6opp1pq6CJeSbVUqcXLaU25aE21VEk1a+P90i+taU011TSkIaW0Jb+heEtaUqRIv3TMcUPx5jSnlFIa1hvvdRVvbW2ti97r0b+nUr8U7e6PctGScqqd4pWiOaV07Lt18e7uvXX3eZEiLWlJOeVU0tZ71VTTmtZUUkm53fnPPdV76+7Hvrzurd9rr2WzBuPnnntupk2blltvvbX2mWe//e1vM3v27Pz4xz/enJsEAACArV53HW83NTXl7rvvzhlnnFGLlcvlHHrooZkzZ85G3cbq1avT3NycN73pTUmSRYsWZenSpTn00ENr2wwZMiT77bdf5syZ0+Vg/Pzzz8+5557bKT5v3rwMHjw4STJ8+PCMHz8+ixYtyrJly2rbjBkzJmPGjMlDDz2U5cuX1+K77rprRowYkQULFuTll1+uxXffffdsv/32mTdvXocnZSZOnJjGxsbcddddHXKYPHlympqaMn/+/FqsUqlkypQpWb58eR544IFafODAgZk0aVKeffbZPProox3q32OPPbJkyZIsXry4FleTmtSkJjWpSU1qqreaPj6hbVj1YlNyzaJKJgwp8u5RbcOqxauTG5+o5B07FNlnh7b4g8tLuXVpKQeOLPLWIW3xe54r5e5nS3nvmGrGDGrL5dalpTy4vJQPjqtm+3bzxhsXl7N4VXLC+Gru6veptpqe+H4aW1bmrl3aYkkyedGlaWrYNvPHnthWU7UpUx67NMsHvjkP7HhcLT6w6flMWnx1nt32bXl0+Htr8SGr/5A9lv40S4ZOzeKh+9fiw1cuyPhlN2fRsPdk2bZ7JkmmDRqY+U3zM795fg4ecHB2rOxY237umrlZ2LIwRww8IkPKQ2rx2a/MzlOtT+W4QcelX7th6fWrr8/qYnWmDZ7WoaZZq2ZlUGlQjhp0VC3WXDRn1upZGVUZlUMGHFKLL1iwoC56r0f/nkYeleWDdm6radnNGbFyQRaMPj4vN76praanfprtX/5D5u18clrLbU3ZE703bdDAJMlTrU9l9iuzs2e/PTOxcWJt+4XNCzO3aW6mNE7Jbv12q8V7qvfW3V99ed1btWpVNlapaD9i3wR33313vva1r+X3v/99kmSPPfbI3//93+cd73jH5tzcG2bFihUZMmRIli9fnu2226630wHYIow7/YbeTqGDxwYc39spdLLXLm/u7RQ6uO+k+3o7Beh2fW0tSvreemQtgt7R3ceZ3XG8vWTJkowePTq33XZbDjjggFr8tNNOy29+85vcfvvtr3sbf/u3f5tf/OIXuf/++zNgwIDcdtttOfDAA7NkyZLsuGPbEy1/9md/llKplFmzZnW6ja7OGB87dmyee+652u9qqzwzRU1qUpOa1KQmNalpC6vpLV9oOybvC2eM/77/9Lbc+8gZ41PHje1TZ4zf+bE766L3evTv6dxhfe6M8anjxibpO2eM33HCHWtr6sPr3ooVK7LDDjts1DH5Zp0xniT77rtv/u3f/m1zrw4AAAB0oS8cb19wwQX50Y9+lFtuuSUDBgzY7Nvp379/+vfv3yne0NCQhoaOT0mse3JjfeuegNnY+Pq3uznxUqnUZXxDOW5qXE1q2lBcTWpK1LShHDc1riY1JWraUI6bGi+VSmmuljrFqyml3QyrLV6UUu3ilMzWopTWLuItRSnZhHhztZSGoqlz7l3EkqLLeGkD8XKqKXcZXzsI7xQvWlPO2nhzmttyT9dv7byhePvrvl68SLFR8XU9saX3Xo/+PRVd/943FO+6x7q399a/b6uv/ltf66v/1tfdvbf+778vrnsb6qmudL71jfDzn/88v/jFLzrFf/GLX+TGG2/cnJsEAACArV53HW8PGzYslUolTz/9dIf4008/nVGjRr3mdS+66KJccMEF+eUvf5mJE9vesm/d9TbnNgEAAKC3bdZg/PTTT+90qnySFEWR008//Y9OCgAAALZG3XW83djYmH333TezZ8+uxarVambPnt3hrdXXd+GFF+ZLX/pSbrrppkyePLnD93bZZZeMGjWqw22uWLEit99++2veJgAAAPQFm/VW6g8//HDe9ra3dYrvvvvuWbhw4R+dFAAAAGyNuvN4e8aMGTnppJMyefLkTJ06NZdccklWrVqV6dPXfh7jiSeemNGjR+f8889PknzlK1/J2WefnR/+8IcZN25cli5dmiTZZpttss0226RUKuXUU0/Nl7/85UyYMCG77LJLvvjFL2annXbKscce+8cVDgAAAD1sswbjQ4YMyaOPPppx48Z1iC9cuDCDBw/ujrwAAABgq9Odx9vTpk3LsmXLcvbZZ2fp0qXZe++9c9NNN2XkyJFJkscff7zD57dddtllaWpqyoc//OEOtzNz5sycc845SZLTTjstq1atyic/+cm8+OKLOeigg3LTTTf9UZ9DDgAAAG+EzRqMH3PMMTn11FNz7bXXZvz48UnWHqT//d//fY4++uhuTRAAAAC2Ft19vH3KKafklFNO6fJ7t9xyS4evH3vssde9vVKplPPOOy/nnXfeJucCAAAAvWmzBuMXXnhhDj/88Oy+++4ZM2ZMkuSJJ57Iu9/97lx00UXdmiBQZ84Z0tsZdHbO8t7OAAAAkjjeBgAAgJ6y2W+lftttt+Xmm2/Ovffem4EDB2bSpEl517ve1d35AQAAwFbD8TYAAAD0jPLrb9Jmzpw5+a//+q8ka98+7X3ve19GjBiRiy66KB/60IfyyU9+MmvWrOmRRAEAAKBeOd4GAACAnrVJg/Hzzjsv999/f+3r++67LyeffHLe+9735vTTT8/111+f888/v9uTBAAAgHrmeBsAAAB61iYNxn/3u9/lkEMOqX39ox/9KFOnTs2VV16ZGTNm5Bvf+EZ+/OMfd3uSAAAAUM8cbwMAAEDP2qTB+AsvvJCRI0fWvv7Nb36TI444ovb1lClT8sQTT3RfdgAAALAVcLwNAAAAPWuTBuMjR47MokWLkiRNTU255557sv/++9e+v3LlyvTr1697MwQAAIA653gbAAAAetYmDcbf//735/TTT8///M//5IwzzsigQYPyrne9q/b9+fPnZ/z48d2eJAAAANQzx9sAAADQsxo2ZeMvfelLOe6443LwwQdnm222ydVXX53Gxsba96+66qq8733v6/YkAQAAoJ453gYAAICetUmD8WHDhuXWW2/N8uXLs80226RSqXT4/jXXXJNtttmmWxMEAACAeud4GwAAAHrWJg3G1xkyZEiX8Te96U1/VDIAAACwNXO8DQAAAD1jkz5jHAAAAAAAAAC2NAbjAAAAAAAAANQ1g3EAAAAAAAAA6prBOAAAAAAAAAB1zWAcAAAAAAAAgLpmMA4AAAAAAABAXTMYBwAAAAAAAKCuGYwDAAAAAAAAUNcMxgEAAAAAAACoawbjAAAAAAAAANQ1g3EAAAAAAAAA6lpDbycA0Nv2unqv3k6hg/tOuq+3UwAAAAAAAKgrzhgHAAAAAAAAoK4ZjAMAAAAAAABQ1wzGAQAAAAAAAKhrBuMAAAAAAAAA1DWDcQAAAAAAAADqmsE4AAAAAAAAAHXNYBwAAAAAAACAumYwDgAAAAAAAEBdMxgHAAAAAAAAoK4ZjAMAAAAAAABQ1wzGAQAAAAAAAKhrBuMAAAAAAAAA1DWDcQAAAAAAAADqmsE4AAAAAAAAAHXNYBwAAAAAAACAumYwDgAAAAAAAEBdMxgHAAAAAAAAoK4ZjAMAAAAAAABQ1/rEYPzSSy/NuHHjMmDAgOy333654447Nup6P/rRj1IqlXLsscf2bIIAAAAAAAAAbLF6fTA+a9aszJgxIzNnzsw999yTSZMm5bDDDsszzzzzmtd77LHH8g//8A9517ve9QZlCgAAAAAAAMCWqKG3E7j44otz8sknZ/r06UmSyy+/PDfccEOuuuqqnH766V1ep7W1NSeccELOPffc/M///E9efPHFDd7+mjVrsmbNmtrXK1asSJK0tLSkpaUlSVIul1Mul1OtVlOtVmvbrou3tramKIrXjVcqlZRKpdrtto+vy3tj4g0NDSmKokO8VCqlUql0ynFDcTWpqc/WVOqXIqW2eNGScqqd4pWiOaUUaSk1dsy9aE5SpLVTvClJKa2lfh1rKppSrBcvpUilaE415VRLDemXtd8rUqQlLSmnnEoqte2rqaY1ramkknK71xO1pjXVVNOQhpTa5b6heEtaUqSo/bwNxdfdj32q91KkmlIaSkVKbSWlpZoUKaVfuW3btnjSb72XXzVXk1KShk7xUkopOsSLImkpSimnSGW9eJJUU0m11HY/ldOactGaaqmSarv7r1y0ppzWHu+99e/X5jSnlFIa2u1qN9RjPdF77deDLWqNqMd1T03dVlP7tea11oiWopRyqUil3XpVLZLWopRKqUi5Xby1SKpF5/WttZqNWvfWrRU9sX/qHH/9da9f+vXY/mmdrta3DcVbW1vrovfq8e9JTd1b0/o1AADwOs4Z0tsZdHTO8t7OAIA3QK8OxpuamnL33XfnjDPOqMXK5XIOPfTQzJkzZ4PXO++88zJixIh84hOfyP/8z/+85s84//zzc+6553aKz5s3L4MHD06SDB8+POPHj8+iRYuybNmy2jZjxozJmDFj8tBDD2X58rYd46677poRI0ZkwYIFefnll2vx3XffPdtvv33mzZvX4UmZiRMnprGxMXfddVeHHCZPnpympqbMnz+/FqtUKpkyZUqWL1+eBx54oBYfOHBgJk2alGeffTaPPvpoLT5kyJDsscceWbJkSRYvXlyLq0lNfbamkUdl+aCd22padnNGrFyQBaOPz8uNb2qr6amfZvuX/5B5O5+c1nLbkGHiE99PY8vK3LXLpzrWtOjSNDVsm/ljT2yrqdqUKY9dmuUD35wHdjyuraam5zNp8dV5dtu35dHh7820QQOTJE+1PpXZr8zOnv32zMTGibXtFzYvzNymuZnSOCW79dutFp/fND/zm+fn4AEHZ8fKjrX43DVzs7BlYY4YeESGlNse5M9+ZXaean0qxw06Lv3aDUKuX319VherM23wtCSp3V99qfcmDCny4PJSPjiumu3bzXxuXFzO4lXJCeOrHYbgP1lUzkstyccntD2xnCT/+nA52zQkH96lLd5cTf714UpGD06OGNMWf7EpuWZRJROGFHn3qLYnohevTrIsWTJ0ahYP3b+tppULMn7ZzVk07D1Ztu2ebTW9MDdjXpjT47237v5LkuaiObNWz8qoyqgcMuCQWnx5dXmuf/n67Nqwa/bv35Z7T/Re+7/7LWqNqMd1T03dVlP7NeW11ogbn6jkHTsU2WeHtviDy0u5dWkpB44s8tYhbfF7nivl7mdLee+YasYMasvl1qWljVr37qqsXRN6Yv+0zpDVf8geS3+6UevetEEDe2z/tM6sVbMyqDQoRw06qhbb0Lq3YMGCuui9evx7UlP31rRq1aoAAAAAfVupaP+y9zfYkiVLMnr06Nx222054IADavHTTjstv/nNb3L77bd3us7//u//5s///M/zu9/9LsOGDcvHP/7xvPjii7nuuuu6/BldnTE+duzYPPfcc9luu+2SOONBTWp6Q2s6d1ifO2N86rixSfrOGeN3nHDH2pr6UO+95ayb+tQZ4wv7n9Dnzhjfd5ddO9bUy2eM33nCnW05bklrRD2ue2rqtpre8oUbarG+csb47/uvfdejvnLG+NRxY/vUGeN3fuzOuui9evx7UlP31rRixYrssMMOWb58ee04k66tWLEiQ4YM8bsCgK2dM8a3OONOv+H1N3oDPTbg+N5OoZO9dnlzb6fQwX0n3dfbKfR9fW0tij7aHJtynNnrb6W+KVauXJn/9//+X6688soMGzZso67Tv3//9O/fv1O8oaEhDQ0dy1/35Mb61j0Bs7Hx9W93c+KlUqnL+IZy3NS4mtS0oXiP11Q0d5nLhuINRdMmxIsu46UNxMupplw0pTkdf3b11X/ra3313/pa0vVbZ24ovv7PWz++/u+/L/Re9dUBSktRWjvxXj/3aqlzMGsH4esrNhgvdRmvppRqF/F1A6FO8VcH4evr6d7r6n4tNhDfUI91Z+911R9bxBpRj+uemrqtpq7Wmg2tEdWilGoX61VrUUprF/ENrW+vt+6tvyZ05/6pc/z11732a05375/a29D6tn58XU9s6b1Xj39PauremjaUKwAAANB39OrR+7Bhw1KpVPL00093iD/99NMZNWpUp+0feeSRPPbYYznqqLa3bVz3av6GhoY8+OCDGT9+fM8mDQAAAAAAAMAWpfNL4d9AjY2N2XfffTN79uxarFqtZvbs2R3eWn2d3XffPffdd19+97vf1S5HH310/vRP/zS/+93vMnbs2DcyfQAAAAAAAAC2AL3+fm8zZszISSedlMmTJ2fq1Km55JJLsmrVqkyfvvbzGk888cSMHj06559/fgYMGJA999yzw/W33377JOkUBwAAAAAAAICkDwzGp02blmXLluXss8/O0qVLs/fee+emm27KyJEjkySPP/54l5/xBgAAAAAAAAAbo9cH40lyyimn5JRTTunye7fccstrXvdf//Vfuz8hAAAAAAAAAOqGU7EBAAAAAAAAqGsG4wAAAAAAAADUNYNxAAAAAAAAAOqawTgAAAAAAAAAdc1gHAAAAAAAAIC61tDbCQAAAAAAAPSWva7eq7dT6OS+k+7r7RQA6o4zxgEAAAAAAACoawbjAAAAAAAAANQ1g3EAAAAAAAAA6prPGAcAAOgt5wzp7Qw6O2d5b2cAAAAA0O2cMQ4AAAAAAABAXTMYBwAAAAAAAKCuGYwDAAAAAAAAUNcMxgEAAAAAAACoawbjAAAAAAAAANQ1g3EAAAAAAAAA6prBOAAAAAAAAAB1zWAcAAAAAAAAgLpmMA4AAAB16tJLL824ceMyYMCA7Lfffrnjjjs2uO3999+fD33oQxk3blxKpVIuueSSTtucc845KZVKHS677757D1YAAAAA3cNgHAAAAOrQrFmzMmPGjMycOTP33HNPJk2alMMOOyzPPPNMl9uvXr06u+66ay644IKMGjVqg7f79re/PU899VTt8r//+789VQIAAAB0m4beTgAAAIC+Y6+r9+rtFDq476T7ejuFLdbFF1+ck08+OdOnT0+SXH755bnhhhty1VVX5fTTT++0/ZQpUzJlypQk6fL76zQ0NLzm4Ly9NWvWZM2aNbWvV6xYkSRpaWlJS0tLkqRcLqdcLqdaraZarda2XRdvbW1NURSvG69UKimVSrXbbR9PktbW1o2KNzQ0pCiKDvFSqZRKpdIpxw3F1aQmNalJTWpS0+vES41pKJpSpJTWUr+2cIpUiuZUU0611NBFvJJqqdKWY1pTLlpTLVVSTbt40ZpyWtNa6pcipXbxlpRT7RQvpZQiRfqlLZckaUlLl/HmNKeUUhrWG7F0FS9SpCUtKaecSrscNxSvpprWtPaN+yltvdev3HbbRZG0FKWUU6TS7vTLWrxUpNL26021SFqLUiqlIuV28dYiqRalNJSKlNrHq0k1neMt1aRIKf3KRVpKjW25F81JirS2i62NNyXr9ViSHuu9fum39r5LNQ1pSKldj20ovqEe647ea21t3XLXiLxB695GrhGVojmldOy7dfHu7r119/nrrRGVVFJud/5zT/XeuvuxL++f1u+112IwDgAAAHWmqakpd999d84444xarFwu59BDD82cOXP+qNt++OGHs9NOO2XAgAE54IADcv755+fNb35zl9uef/75OffcczvF582bl8GDBydJhg8fnvHjx2fRokVZtmxZbZsxY8ZkzJgxeeihh7J8+fJafNddd82IESOyYMGCvPzyy7X47rvvnu233z7z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msE4AAAAAAAAAHXNYBwAAAAAAACAumYwDgAAAAAAAEBdMxgHAAAAAAAAoK4ZjAMAAAAAAABQ1wzGAQAAAAAAAKhrBuMAAAAAAAAA1DWDcQAAAAAAAADqmsE4AAAAAAAAAHWtTwzGL7300owbNy4DBgzIfvvtlzvuuGOD21555ZV517velaFDh2bo0KE59NBDX3N7AAAAAAAAALZuvT4YnzVrVmbMmJGZM2fmnnvuyaRJk3LYYYflmWee6XL7W265JR/96Efz61//OnPmzMnYsWPzvve9L08++eQbnDkAAAAAAAAAW4JeH4xffPHFOfnkkzN9+vS87W1vy+WXX55Bgwblqquu6nL7f//3f8/f/u3fZu+9987uu++e73znO6lWq5k9e/YbnDkAAAAAAAAAW4KG3vzhTU1Nufvuu3PGGWfUYuVyOYceemjmzJmzUbexevXqNDc3501velOX31+zZk3WrFlT+3rFihVJkpaWlrS0tNR+ZrlcTrVaTbVa7ZBLuVxOa2triqJ43XilUkmpVKrdbvt4krS2tm5UvKGhIUVRdIiXSqVUKpVOOW4o3mM1/eOOa+NFc5IiraXGjjUVTUlKaS3161hT0ZRivXgpRSpFc6opp1pq6CJeSbVUacsxrSkXramWKqnm1fgXnnI/vW5NRfqt9xKY5mpSStLQKV5KKUWHeFEkLUUp5RSpdBUvFamU2uLVImktSqmUipTbxVuLpFqs7YEibd8oFy0pp9opXimaU0qRlk491v291y9rv1ekSEtaUk45lbT1XjXVtKY1lVRSbvd6ota0pppqGtKQUrvcNxRvSUuKFLWft6H4uvuxT/VeilRTSkOpSKnd/dpSTYqU0q/ctm1bPD3We0k2bo1IUi5aU05rj/fe+vdrc5pTSikN7Xa1G+qxnui99uvB1rfubWRNpcae2z9l03tv7V/B668R63TVYxuKb27v9Yn7KW29136t6e790/rrW2s1G7XurVsr+spjo37p12P7p3U2pfdaW1v74BrhsZHHRt3fe+v3GgAAAND39Opg/Nlnn01ra2tGjhzZIT5y5Mg88MADG3Ubn//857PTTjvl0EMP7fL7559/fs4999xO8Xnz5mXw4MFJkuHDh2f8+PFZtGhRli1bVttmzJgxGTNmTB566KEsX768Ft91110zYsSILFiwIC+//HItvvvuu2f77bfP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qFQq9UImbMlaW1t7OwVgC+WxC93FMRbQW15++eWsXr26t9MASNL2nI7H2fWjobcTYMtVrVZTLre9tqK1tTWVSqUXM2JLtK5v1qxZk/vvvz9FUWSnnXbKjjvumGTtDsdAgdeyrodWr16dm2++OUuXLs173vOeDBs2LEOHDtVDbJR1fdTS0pLnn38+LS0t2WmnnVIqlfQQG23dY6NVq1bl4osvzqpVqzJkyJCcfPLJedOb3pRyuayfeF3r1qPly5fnsssuy6c//ekMHjy4t9MC+rCWlpa0tLTk5ZdfztChQ3s7HbZQa9asycKFC9PS0pLdd989/fv37+2U2AIVRZHW1tY0NLQ95bz+84fwWlasWJGRI0fmvPPOy+c+97neToctUFNTU5YtW5bRo0f3dipswVatWpXLLrssixcvzlve8pZ88IMfrM0r2PKVCi9zYDO0f+L3yiuvzMknn5zBgwd7sMsmWTccWLFiRd797nenKIr8/ve/z3777Zejjz669gDYEIENWdcbK1euzNSpU9OvX78888wzSZLDDz88n/nMZ7LPPvvoIV7Tun3XypUr87GPfSx/+MMfkiTvfe9789WvfrWXs2NL89JLL2XixIkZNWpUhgwZkrvuuivjxo3LZz7zmfzZn/1Z+vfvb01ig9YNxVesWJEJEyZkv/32y89+9rPeTgvow1auXJkPfehDWbFiRRYuXJi//uu/ztFHH52pU6f2dmpsQVasWJFDDz00L7zwQlatWpXtttsu3/zmN7P//vtn22237e302EKsXLkyp556ap588skMHz48hxxySE466aSUSiXPF7JRVqxYkYkTJ2bffffNf/zHf3T6vuMoXs9LL72Uww8/POPGjcs555yT3XbbrbdTYgu07nnmN7/5zVm5cmVaWlpy1FFH5Qtf+EJKpZJ1qA54RMImK4oi5XI5q1evzoEHHpizzjorX/ziF7Nq1aqUy2Vvt8VGK5VKaW5uzgc+8IHsvPPO+c///M/ceOONefe7351zzz03n/nMZ2rbeQ0PXVl3gP3Xf/3XmTBhQv77v/87S5cuzXnnnZdnnnkmf/M3f5O5c+d6wMIGrdunrVy5Mvvuu28aGxtz9tln5+ijj85NN92U+++/v8O2sCHr+uPcc8/Nbrvtlttuuy033nhjFi1alJ122inf+MY3csUVV2TNmjXWJLpUFEVtKD5x4sS8613v2uBQ3ONtIEleeeWVvPOd78ygQYNy6qmn5qyzzsqPf/zjzJw5M7Nmzert9NhCNDU15cgjj8wuu+ySn/zkJ/nJT36SvffeOx/5yEfyne98J88++2xvp8gWYNWqVdl3333zxBNPZMqUKXnyySfzta99LR/+8IdrQ3GPX3gtL730Ut7+9rfnoIMOqg3F77vvvtx000156KGH8sILL9SeA4KurFmzJh/96EfzyCOP5IEHHsgll1yShQsX9nZabGFWr16dP/mTP8k73vGO/OxnP8ttt92WiRMnZuHChSmXy7Xnc6xFWzZvpc4mK5VKaWlpyd/93d9lhx12yJ/8yZ9k7ty5OeOMM3L++ec7c5xN8uKLL2b16tU555xzMm7cuIwbNy5TpkzJ7rvvnk9+8pNpbGzMRRddZIjABjU1NeWxxx7LMccck2HDhiVJPvnJT2aXXXbJN7/5zXz+85/Pt7/97bz97W/v5Uzpi0qlUpqamnLcccflHe94R/793/89DQ0Nede73pXZs2fX+mvcuHHOdOA1rdtPrVixIoMGDUq1Wk1RFNlmm20ya9asfPKTn8zVV1+dXXbZJR/4wAec7UAnpVIpr7zySnbfffe87W1vy09+8pMkyTe/+c3cf//9Wb16dfbZZ5+ceuqptSeXrUewdfvtb3+boijyne98p/Y4eL/99suFF16Yb3/722lsbMwHP/jBXs6Svm7ZsmV59tlnc+6552bSpElJkne+8505/fTTc+GFF6axsTGf/OQn069fv17OlL7s2muvzQ477JCf/vSn2WabbdLc3Jwf/ehH+cpXvpL3ve99+eUvf+ljhXhN3/72t/Pkk0/mrLPOSpJMnz4999xzTx588MGMHj06e+21V/75n/8548eP10d0ae7cuVm5cmV+9KMf5b777stVV12VJDn11FOdOc5G+9GPfpTRo0fn4osvrj32ectb3pLbbrstH/vYx7LTTjvl4x//eN72trc5Jt+CudfYLJVKJSNGjMixxx6bf/qnf8oHPvCB3HnnnTnjjDO6PHPcWXa8locffjgPPPBA7evtttsu06ZNy6WXXpqrrroq3/ve93oxO/q6xsbGjBw5svZ5eOu8973vzV/91V+ltbU1P/zhD1MUhVfz0aXnnnsukydPzmc+85naZ+H9+te/zr333puPfOQjef/7358DDjggSWpP5sD61g3C+/fvn2eeeSblcjmVSiVNTU0ZMGBArrjiigwePLj29vyeyKErq1evzpve9KasWLEizz33XE488cRcdtlleemll7J06dJcdtlltSGXA3CgsbExTz/9dB5//PEka4+7DzjggHzxi1/Mdtttlx/84AdZtGhRL2dJX1YURV566aW8+OKLtccmL7/8cpLkggsuyAknnJDTTz89Dz30UG176MqSJUuyePHiDB48OEnSr1+/TJs2LV/+8pezbNmynHzyyUk8BmbDjj/++Pz5n/95DjzwwLz//e/Pgw8+mK9+9at55JFHcvbZZ2flypU5/fTT89JLL+kjujR16tR8/vOfz0EHHZRTTjklf/EXf5Hbbrstl1xySR5++OFO23uOkK68613vyhe+8IWMGDEi5XI511xzTc4888yMGDEijY2Nuf/++3P00Udn8eLFjsm3YO45NkupVMrMmTPziU98IoMGDcqMGTNy5JFHbnA47gELXSmKIsOHD8/xxx+fn/3sZ7n33ntr32tsbMzRRx+dI488Mv/7v//rAJwkXT8RUy6Xs/fee+fGG2/M3LlzO3zvyCOPzCGHHJLvf//7eeWVVzxgoUujRo3KZz/72ey///5Jkl/+8pf5i7/4i3zxi1/MD3/4w3znO9/J008/7ckcOlj/IHrdW2qdeuqpueeee3L66acnWbs/e+WVVzJgwIB873vfy5133pmbb765N1JmC/CmN70pv/71r9Pa2prhw4fnkUceyU9/+tP827/9W2666aacd955ue+++3L11Vf3dqpAHzB06NA0NjZmzpw5SdoeK++zzz753Oc+l5tvvjn/+7//25sp0seVSqW89a1vzZ577ll77DJw4MCsWbMmSXLRRRdl6tSpOfPMM2vbQ1cOOOCAbL/99vn5z39eizU2Nuawww7L9OnTM2/evPzud7/rvQTps9btu8aMGZOvfe1rOeKII3L//ffn4osvzvve976MHj06J510Uo455pjMnTs3zz//fC9nTF+zrocGDhyYI444IpVKJUlyyimn5BOf+ERuu+22fP3rX6+9rfoPfvCDPPzww54jpIN1fTRhwoRMmTIl5XI5r7zySr7+9a/na1/7Wq644opcddVV+eIXv5g1a9bkrrvu6uWM+WP462eTrHsSuCiKNDQ0ZNCgQWlubs6AAQNy2mmn1YbjZ555ZlatWpWLL74473//+3s5a/qC9QcIra2ttYPqY445JosXL853v/vdDq/gGzZsWCZMmJBbb701q1evfkPzpe9Z1zNr1qzJPffck7vvvjtPPvlkkuTss8/O+PHj8/GPfzzz58/vMEB///vfn379+mXZsmW9lTp9VPsXb40cObJ28DRgwIB897vfzec///lMnTo173znO7P//vvnmWee6c106UNaW1tTLpezevXq/Od//mf+5V/+JQ8//HCWLVuWXXfdtXbgdO655yZZ21PJ2sdPY8aMyXbbbdeb6dMHtX+MPXz48Pz85z/PRz/60UyfPj277757iqJIuVzO0UcfnaIo8vvf/76XMwZ6Q1EUHd4hac8998xf/dVfZcaMGbn55ptTLpfT2tqaJHn3u9+dQw45JP/1X//VW+nSR7W0tOSVV17JCy+8UIv90z/9U1588cUcf/zxSZL+/fvXhuP7779/VqxY0Su5suV461vfmu222y5XXHFFHnzwwVp84MCB+cu//MssWrQot956ay9mSF/V/gU3I0eOzPnnn58rrrii9nF46x4nT5w4MUVR1PZzsM76L9pq3yef+tSn8pd/+Ze57bbb8o1vfCNnnHFGTjrppDzyyCO9kSp9WPs+WveYesCAAfnVr36VT3/607W1aPjw4Rk8eHCGDh3aW6nSDXzGOK9p/c9JWLlyZbbddts0Nzenf//+Sda+PVJra2saGxtz2mmnJUl+8Ytf5D3veU/uvvvuXHHFFb2SO33Huj5atWpVrrzyypx88skZPHhwWlpa0tDQkMMPPzxLlizJOeeck9bW1px00kmZOnVqkrVv2z9hwoReroDeVhRFKpVKVqxYkXe/+921ocB+++2XI444ImeeeWZuuumm/Omf/mmOPvrofOtb38pBBx2U7bffPnPmzEljY2NtzWLrtTH7tGTtE8nrrPvssm222SZjx47tEGPrtG49WrlyZaZOnZp+/frlmWeeycyZM3PYYYflH/7hH/JXf/VXWbFiRc4666w888wzOeOMMzJw4MD89re/zYoVK7LNNtv0dhn0sg2tR+veen/kyJG57LLLOryAp1qtplKp5C1veUvGjx/fW6kDvWTlypU59dRT8+STT2b48OH50z/900yfPj1nn312HnnkkRx77LH58Y9/nCOPPLJ2nf79+9cev0Cyto8+9KEPZcWKFVm4cGH+6q/+Kh/60IcyZcqUnH766bnooovy4Q9/OD/5yU9qj4/L5XIGDBiQl19+OQMGDPA4mDQ1NWXZsmUZPXp0krUvGh0xYkSuuOKKHHTQQTn99NNz3nnnZa+99kqSbLPNNpk8eXK23Xbb3kybPqS5uTmLFy/OL37xi6xZsyYjRozIiBEjcsghh2Ts2LEZM2ZMba1Z95j5zjvvzM477+xFxiTpuodGjhyZ97znPSmVSqlUKmltbU2lUsnf/u3fplwu54wzzsjy5csza9asHH744b1dAn3Aa/XRupNnGhsbk7StRb/61a/Sv3//jBkzptfy5o9nMM4GrXvC7uWXX84Pf/jD3HzzzXniiSfS2NiYUqmUL3zhC9lnn30ydOjQVCqVVKvV2nD817/+dX7729/m2muvzTHHHGOIsBVbd4bT6tWrc+CBB2bhwoV5/PHH86UvfSmDBw9Oc3Nz+vXrl7/4i79IQ0NDLr300tx66615+9vfnqFDh+Z73/te/r//7/+rfU4VW6dSqZTm5uZ84AMfyM4775yvf/3reeSRR/Lf//3f+ad/+qc89dRT+eY3v5k5c+bkyCOPzN/93d+lXC5n9913z80335yrr746I0eO7O0y6EWbsk9rr1Qq5eqrr851112Xn/zkJ7UYW691A8q//uu/zoQJE3LVVVdl2LBhueKKK3LttdfmL//yL3PZZZflc5/7XMaNG5e/+Zu/yQ033JD+/fvn+eefzze/+c3a2Q9snV5vPTrzzDOz7777dlqPyuVyfvjDH+bee+/Neeed10vZA71h1apV2XfffTNu3Ljst99++e1vf5uvf/3rueGGG3LNNdfk6quvTv/+/XPsscfm7//+77PTTjulKIr853/+Z372s5/1dvr0Ea+88kre+c53Zvz48fmLv/iLLF26NN/+9rdz11135ZRTTsn06dPT2NiY8847LxMmTMhRRx2V5ubm/Mu//Et+8pOfZODAgb1dAn3ASy+9lMMPPzzjxo3LOeeck9122y2VSiUtLS15+9vfnltuuSWHH354Pve5z+Xoo4/OwQcfnN/85jeZM2eOxy8kWdtDn/jEJ/LKK6/kiSeeyP7775+77rorv/zlLzN9+vTMmDEjI0aMqG3//PPP58c//nHOO++8/Pu//3t22GGHXsyevmBje2jdvGLd2b8vvfRSfvazn+UDH/hA7Z0mPb+z9drYPlo3EH/++edzzTXX5O///u/zgx/8wIvVt3Clwgf30oV1O42VK1fmyCOPzIgRI7L77rvnpJNOyuOPP55777031157bY477rh87GMfy/Dhw2vXu/zyy3PKKafkP/7jP/LBD37Qjoa0tLTkU5/6VBYuXJi99tord9xxRyZPnpzzzz+/w3A8Se64447cfffdufbaazNhwoQceeSRef/73+/FFWTZsmU54ogjcuGFF+Y973lPkmTFihX5z//8z5x88sn5m7/5m3zta19Lklx33XX5/e9/n0qlkgMOOCDvete79NBWbHP3affff3+uvfbafOUrX8l3v/vd/Nmf/VkvV0Jf8corr+SQQw7JMcccU3u3nCS5+eab841vfCMrVqzI5Zdfnj322CPPPfdcbr311lQqlbz5zW/O3nvvbT3aim3uenTfffflpz/9ab761a/me9/7Xj7ykY/0ciXAG+nf/u3fcumll+bmm2/ONttsk+bm5vzoRz/KBRdckNGjR+emm25KuVzOt7/97VxzzTV58sknM3LkyJx66qn50Ic+ZL9DkmT27Nn57Gc/m1tuuSXDhg1LksyZMycXXnhhli1bli984Qs54ogj8uSTT+bLX/5ynnjiiQwePDgnnnhijjzySH1E1qxZkw9/+MO56667Mnr06Oy///459dRTs9tuu9XeurihoSEPPvhgZs6cmbvvvjuvvPJKGhsbc/755zueIi+99FIOOuigTJgwIWeccUb22WefPPXUU9lxxx3z4IMP5q//+q+z33775YILLkiS3Hvvvfnud7+ba6+9NhdffHE+8pGPWIu2cpvaQ8naPnrHO96RH/zgBznhhBPMKtjkPrrvvvvy/e9/P9dee20uuOCCfPjDH7YWbekK2IBVq1YV++23X/HBD36wePrpp4uiKIrrrruu+OUvf1kURVH88pe/LP7kT/6kuO6664qiKIpqtVoURVF86lOfKn74wx/WYuvibL2q1Wpx1llnFd/4xjeKVatWFf/4j/9Y7L///sWnP/3p4qWXXiqKoiiampo6XKe1tbXD9fURzzzzTLHddtsVl156aYf4mjVriu9+97vF0KFDiyuuuGKD19dDW7dN3aetXLmy+O53v1t8+MMfLq6//vqiKPQQbVpbW4sPfvCDxcknn1w0Nzd3+N5//dd/FQceeGBx5plndtq3QVFs3np0+eWXF+9///uL//zP/yyKwnoEW5uvfOUrxZgxYzr87a9Zs6a49tpri7322quYPn167XsvvPBCsWrVquK5554risKxFG1uvfXWYtiwYcXdd99dFEXbvuTuu+8ujjzyyOKYY44pFi1a1OE6LS0ttW31Ebfccktx8MEHF7fcckvxzW9+s3jHO95RfOpTnyoefvjhoijW9sm6x8arV68unn766WLBggXFE088Ufu+Ptp6NTU1FdOmTSs+8IEP1I6TbrjhhmLgwIHFNddcUxRFUTz++OPFyJEji5tuuql2veuuu6646667iqLQQ1u7ze2hoiiKhQsXFkWhh9j8PrrxxhuLefPmFUWhj+qBt1Jng772ta9l2LBh+d73vpchQ4bkZz/7Wb7whS+kpaUlV1xxRd773vfm//7v/3LxxRfXPsesoaEh3/rWt5LEq6+oKZVKmTlzZpqamjJo0KDMmDEj1Wo1N9xwQ84444zamePrPvslSYfP3dRDFEWR4cOH5/jjj8/PfvazHHjggZk0aVKStZ/1cvTRR+fXv/515s6dm0984hMplUqd+kYfbd02dp/2ta99Le9///uzzTbbZNq0aTnqqKMyfPjw2j6NrU/RxauAy+Vy9t5771x55ZWZO3duDjrooNr3jjzyyNxxxx256qqrctZZZ9XeEQXW2Zz16Pjjj8+xxx6bkSNHWo9gK3TAAQfkBz/4QX7+85/Xjr0bGxtz2GGH5bHHHsv3v//9zJs3L/vss0+22267lMvlDBo0KInHwLQZOnRoGhsbM2fOnOyzzz61xzj77LNPTjvttBx55JH5n//5n4wbN652nXXH5fqIJJk6dWo+//nP56CDDsrBBx+cJLnqqquSJJ/97GczYcKENDQ0pFqtZuDAgRk4cGCHt8TWR1u3xYsXZ8WKFTnzzDPTr1+/fPzjH8+gQYMyZMiQHH/88Vm5cmWmT5/+/7d353FVl+n/x19wDqggkIr4yMzcGC3GDXNBUIOyRFxLplHTRBCYUCuDLCfF3DOXTEvTY46hWQppjqFoU0muFRojKgplbo25ZMphkcM5n98f/jijUzPT4ncOyvv5V+L58LjuR7f3fT73dd/XTWhoKKWlpc7n+vfv7/xv9aHq7df0ocqKXU2bNnX+HvWj6u3XjkXX3kuvPnTzc//vH5Hqas+ePfTo0QM/Pz8GDx7MnDlz6NevH3fccQfDhg1j165dNG3alHvuuQez2YzZfP0+i59KTEn14nA4gKtJBbPZjJeXFzabjZo1azpfvD///HMmTJhAcXGxcwFYqrfKflPJbrc7x5L+/ftz6tQpli9fTkFBgfMz/v7+BAYGkp2dTWlpqcYe+ZGfO6fdfffdzkSmt7e3s4yx5rTqqXL8uXLlCvv27SMnJ4fTp08DMGnSJJo3b86IESP4+9//fl2ysnfv3nh4eHDu3DlXhS5V2K8Zj3x8fGjQoAGg8UikOmrZsiW+vr4sXbqUI0eOOH9eq1Yt4uLiOHbsGDt27ACu32As1ZthGFRUVDj//Pvf/56EhATGjRvHtm3bnHeuAnTv3p3777+fTZs2Xfc7NN8I/PPgS61atYiMjHQeaBg9ejSxsbHs2rWLBQsWUFhYCMDq1auve18XAdi0aRPHjx+nS5curFixgs8++4wxY8bw5Zdf8uabbxIfH09WVhZFRUXOuexf14ekevs1faiSNnpJJY1FAqAT4/KTCgsLOXToEBaLhe+++46CggIsFgvt2rUDYPDgwcTFxVG7dm3at28P/PSJKqleKnfhVSoqKsLHxwebzUaNGjUA8PDwwG634+np6byXNSsri4iICHJycli6dKlLYpeqobIPFRcXs2zZMkaNGoW3tzcVFRWYzWZ69erFt99+y+TJk7Hb7Tz++ON06tQJAJPJRGBgoItbIFWR5jT5NQzDwGQycfnyZbp3745hGBw+fJjOnTsTGRnJhAkT2LJlC+Hh4fTr149FixYRFhbGbbfdxu7du/H09HTOfSKVNB6JyH9TXl7OuXPnuOOOO4Crm7QCAgJYunQpYWFhPPfcc0yZMoXWrVsDULt2be699158fHxcGbZUMUVFRTz11FOcPn2a+vXrEx4eTkxMDJMmTeKrr75iwIABrF271lmBAKBGjRrceeedLoxaqqp//R5iGAYOhwOTyURSUhJubm5YLBbc3d3x9vbmpZdeIjMzU+/nAuCsDnnx4kW6du2K2Wzm8OHD3HXXXdx9990YhsFjjz3GkiVLiIyMJCQkhH79+gHa7CVXqQ/JjaB+JNdSYlx+kslkwuFw4HA4OHv2LAcOHODixYvOv09ISGDEiBG0bt2ahQsXkpOTQ4cOHVwYsbhaZUKztLSUt99+m23btnHy5Ek8PT1xc3Pjz3/+M8HBwdSpU8fZvyqT4x9//DE7d+5k/fr19O/fXwvA1ZRhGLi7u1NSUkJoaCiFhYWcOHGCqVOn4u3tjc1mw8PDg5EjR2I2m3nttdfIzs4mKCiIOnXqsGLFCtasWYO3t7ermyJVjOY0+TXc3Nyw2Wz06dOHu+66iwULFvDVV1/x0UcfMWPGDP7xj3+wcOFCdu/eTVRUFE8//TTu7u60atWKbdu2sXLlSucJX5FKGo9E5D+xWq306tWLJk2aMHnyZFq0aIHJZKKiooKgoCA++eQTevXqRUpKCv369aNHjx5s376d3bt3M2XKFFeHL1VEcXExHTp0oEmTJnTu3JmdO3eyYMECPvjgA9atW8fKlSupUaMGAwYM4JlnnqFhw4YYhsH777/Pxo0bXR2+VBE2m41Tp06RlZXFlStXCAgIoEGDBkRERODm5obJZHImGZ544gnc3d15/vnnuXTpEu++++51JWeleqpcJ7xy5QpeXl7UqFHDeeqyU6dO7Nmzh/379zs3gwYGBhIZGUlMTAxPP/00d999N/Hx8a5sgriY+pDcCOpH8lOUGBfWrVtHXl4eqampzt0vJpPJueO8bdu2jBgxgtWrV9OgQQPuuece3nzzTaKiopg5cybp6elYLBa2bt36o3LqUj1UTjBFRUVERUUREBBAq1atmDp1KidOnCA3N5fJkyfz8MMP89hjj1G/fn3c3d1xOBxYLBY+/vhjMjIynElxqZ7c3NyoqKjg6aefpl69etx3333s2bPnunvoK5Pjw4cPp1WrVuTk5LB+/Xrq1avHe++9R+/evbWxoprTnCY30g8//EBJSQmTJ0+mSZMmNGnShI4dO9KqVStGjRqF2Wxm/vz5fPDBB2zYsIHDhw9jMplITk6mW7duGo+qOY1HIvJLXLlyhcGDB/PVV19RVlbGK6+8wlNPPXVdcrxt27Z88sknpKamMn/+fGbOnImnpydvvvkmISEhrm6CVBHXvh/Vrl0bm83GO++8w6xZs+jVqxdbtmxh6dKltGvXjnXr1nH69GkaNGjA6tWrefDBB/X9RbBarcTGxlJWVsbJkyfp0qULX3zxBVu3biUmJoZx48YREBDg3PBXWZbfarWyceNG+vTp41zbUV+qnqxWK8899xz5+fkEBASQkJDA/fffz/Lly/n666/p3LkzzZo1Y9asWbRs2ZL9+/ezb98+3njjDTw9Pfnuu+8YOHCgq5shLqQ+JDeC+pH8O6oBIFy4cIGpU6cya9Ys526Zxo0bExQUxJw5czAMgyFDhmAYBl27dqV9+/Zs3LiRF154AV9fX/bv30/btm1VUqIaqzzl27NnT/z9/Xn99deZNm0ahw4dwuFwMG7cOCZNmsTGjRvZtWsX8M/TwYcOHWL16tUMHDhQL06CyWQiICCAAQMGMGPGDPr06cPnn3/O888/T3FxMR4eHthsNuDqrr4//elPbNmyhddee82ZFJfqTXOa3GgFBQXk5+c7/+zr68ujjz7K66+/zsqVK1m2bBkAAwYM4Pnnn+fZZ5+lW7durgpXqhCNRyLyS+zZs4eioiLeeecdRowYwa5du3jllVcoLCx0ns6sqKigZcuWrFixgp07d7Jlyxa2b9/OH/7wBwzD0HdhAeDbb7/l1KlTzkpaHh4ePProo0yfPp0zZ84QFxeHYRg88cQTrF+/ni+//JL333+fRx55RH1IsFqthIWF4XA4SE1NZd++fUycOJG0tDSys7PZu3cv8+bNc37e3d2d3NxcxowZw1/+8hclxYXLly/Trl07jhw5gr+/P19++SXDhw/n4MGDREZGsnv3bu68805SUlLo2LEjO3bswGQysW/fPjw9PZk9ezY7duygWbNmrm6KuIj6kNwI6kfyHxlSbX3//feG3W43DMMwli9fbri7uxtTp041ysvLDcMwjL/+9a9GTEyMkZWVZRiGYVy5csVIT0833n33XcNqtRqGYRivvvqqUbNmTePvf/+7axohVca0adOMqKgo44cffjAMwzDef/99IygoyGjZsqWxfft2wzAM45VXXjG6d+9u2Gw2w2azXfe8w+EwHA7H/zxuqXpsNptRXFxsGIZhlJaWGlOnTjW6dOlijBkzxjn2VFRUuDJEqYI0p8mNVjknJSYmGg899JDx5ZdfXvf3586dMx577DFj5MiRht1u1xwmThqPROTXKCkpMTIzM53fcxcuXGi0b9/eSEpKMo4ePer8XOX4IvLvZGdnG7///e+NTZs2XffzkpISY/78+Ub79u2NnJwcwzDUn+R65eXlxqOPPmr06dPH+b3lgw8+MGrVqmWsW7fOMAzDOHHihNGgQQNjy5Yt1z1bWFhoGIbWdqq7oqIio3Hjxsbjjz/uXPfbvXu3ERgYaCQmJhoLFy40IiMjjU2bNhkXL1780fMvv/yyUatWLeNvf/vb/zhyqSrUh+RGUD+S/0Y1+aqprKwskpKSWLVqFZ06dWLkyJE4HA4SEhIwDIOJEyfywAMP8Pnnn5ORkcHRo0dJTEzkkUceAeD48ePMmjWL2bNnk56eTuvWrV3cInG1PXv20KNHD/z8/Bg8eDCnT5+mX79+7N27l2HDhrFmzRqaNm3KPffc85PlQLWTuHqrLL9mGAZmsxmz2YzNZqNmzZo8++yzAHzwwQdMmDCBGTNmsHjxYj766CMyMzNdHLlUBZrT5LeqHIMqVd6XCNC/f3+Sk5NZvnw5Y8aMITAwEAB/f38CAwNJS0ujtLTUeSpLqjeNRyLySxn/v2x1rVq1iIyMdP589OjRuLm5sXz5cgBnWfXVq1fTpUsX53wk8q9atmyJr68vS5cupUWLFrRs2RKAWrVqERcXx4svvsiOHTsIDg5WVRK5zqlTp7h8+TITJkzAw8ODESNG4OXlhZ+fH0OGDKGoqIiYmBhCQ0MpLS0F/vk9umnTps7fo/Wd6skwDMaNG8fZs2dJSEjAbDZTUVFBly5duPfeezl37hyjR4/mypUrrFmzhiVLltCrVy/q169Pbm4u33zzDZs3b2bDhg1ERES4ujniAupDciOoH8nPocR4NRUREYFhGPzpT39i6dKldOjQgbi4OAASEhKcJZPGjx/PmjVryMrKYsGCBTRp0oQffviBmjVrUl5ezieffKK7zITCwkIOHTqExWLhu+++o6CgAIvFQrt27QAYPHgwcXFx1K5dm/bt2wPo3rJq7l+TUEVFRfj4+GCz2ahRowZwteSf3W7H09PTmRzPysoiIiKCnJwcli5d6pLYperRnCa/ReV4VFxczLJlyxg1ahTe3t5UVFRgNpvp1asX3377LZMnT8Zut/P444/TqVMn4Or1D0pMyLU0HonIL/Wv70SGYeBwODCZTCQlJeHm5obFYsHd3R1vb29eeuklMjMzNf8IAOXl5Zw7d4477rgDuLq5LyAggKVLlxIWFsZzzz3HlClTnButateuzb333ouPj48rw5YqatOmTRw/fpwuXbqwYsUKPvvsMzIyMkhNTWXbtm3ExMTQsGFDioqKfrSpovLPWuepvtzc3Bg3bhzffvstU6dOJSUlhfDwcGw2G9u3b2fYsGEAPPPMM+Tm5rJnzx42bNgAgLe3N2FhYUyZMoXmzZu7sBXiSupDciOoH8nP4WYYukCouqlc6LXZbAQHB2MYBitWrKBDhw64u7tjsVhISEhg4sSJTJ482flcZmYmdrud8+fPExoair+/P3Xr1nVdQ6TKOHbsGBEREezatYuzZ8/SqVMntmzZQnh4OACffPIJI0aMoHPnzqSlpXHgwAE6dOjg4qjFVSqTUKWlpbz99tts27aNkydP4unpiZubG3/+858JDg6mTp06132+vLycyMhIPv74Y9avX0///v21wUI0p8lvUjmGlJSU0LVrVwoLC4mPj2fq1Kl4e3tjs9nw8PAA4K233uK1116jpKSEoKAg6tSpw4oVK1izZg0DBw50cUukKtB4JCI/l81m49SpU2RlZXHlyhUCAgJo0KDBdadSrq1esmTJEp5//nkuXbrEu+++S3R0tKtClyrEarXSq1cvmjRpwuTJk2nRogXwz/koNzeXXr160bZtW/r160ePHj3Yvn07zz77LNu2bdMGLHGqHG+mTJnCyZMnWbZsGc8++ywHDhxg8+bNzu/MYWFh7Nq1i5CQEHbu3OnqsKWKKigoYOzYsZjNZp555hkmTJiAr68vW7Zs+dFntaYjP0V9SG4E9SP5T5QYr6Z+7sLdlClTGD9+/E+Wvpbqad26deTl5ZGamurcEXzixAn69OlDVlYWt99+OwkJCdjtdsaNG8c999zD8OHD8fHxYebMmWzatAmLxcLWrVvVr6qhyiR3UVERUVFRBAQE0KpVKx5//HFOnDhBbm4u69ev5+GHH+axxx6jfv36zueWLFnC6NGjycjIYODAgVROX/riIprT5LeoqKggKSmJwsJCWrduzWeffca9997LzJkzf5Qc/+yzz8jJyWH9+vUEBgYSFRVF79699RIlThqPROS/sVqtxMbGUlZWxsmTJ+nSpQtFRUVs3bqVmJgYxo0bR0BAAPDP786vvfYaTz31FOvXr6dPnz76HixcuXKFQYMG8cUXX3DHHXfQpUsXZ7l9wzCw2+2YzWaOHDlCamoqOTk5lJWV4enpycyZM/nDH/7g6iZIFVA5xpSUlODl5cVLL73E0aNHWb58Oenp6bz66qssWLDAWfkvJiaGFi1aEBMTw8svv8zdd99NfHy8i1shVVFlQmrv3r00b96czz//HPjnd+VK124C0zuVXEt9SG4E9SP5d5QYr2au/Ydd+Q/eZrM5v+Reu3D35ptvEhcXR2pqKqmpqa4MW6qQJUuW8MQTTzBt2jSee+45Z3J88ODBNGzYkDlz5pCdnc1bb71FRkYGTZs25dixYxw+fJjbb7+dlJQUKioqmDt3ru4zq6ZKSkqIiIigYcOGLFmyhICAAN5//328vLzo2bMn27ZtY8aMGTz11FPXnQofPXo0oaGhDB48WIuBAmhOkxvDMAwmTZpEQEAAsbGxvPLKK/z1r3+lY8eOP5kch+uvg9B4JKDxSER+HqvVSlhYGIGBgTz//PMEBwfzj3/8g9tvv50jR46QmJhI586dmTVrlvOZ3Nxc2rdvT1paGkOHDtW8IwBs376d1NRUXnzxRQ4cOMCbb75J165dfzI5XlpaSlFREefOncPPz49GjRqpHwlWq5XnnnuO/Px8AgICSEhIwNvbmyFDhrBlyxY8PDyYOHEipaWltGzZkv3797Nv3z6OHTuGp6cnQ4YMITExke7du7u6KVJFFRYWkpiYiJubG1OmTFGVCvnF1IfkRlA/kp+ixHg1UrlIV1RU5LzH19vbG+DfLtwtXbqURo0a0bt3b1eGLlXAxYsX8fPzcy7ojho1ihdffJHx48fj4eHBpk2beO+99/jjH//Igw8+SHl5OX/961+x2+1ERUXh7e3NwoULefbZZ/nss8+cd5xJ9TN9+nR2797N6tWr8fPzY+PGjUyYMIGKigqWLl1K9+7dWbBgAe+99x5/+9vfAK7bxadFHAHNaXJjVVRUUF5ejpeXF2VlZcyZM4cPPvjguuT4tTuIRa6l8UhEfg6bzcawYcMoLi7mvffew8PDg8zMTAYNGsRbb73FoEGDOHnyJB07dmTlypU89NBDzme/+uormjdvru/B4lRaWsonn3zCgw8+iMlkYtGiRc7k+JNPPum8g/7azXwilS5fvkxwcDBNmzalXr16/P3vf6e4uJgpU6awb98+OnXqxNChQzl48CCbN28mMzMTX19f3njjDRo0aMDs2bNZtGgRu3btolGjRq5ujlRhlac1TSYTKSkp9OjRw9UhyU1GfUhuBPUj+VdKjFcTlQt2Bw8eZNSoUZSUlHDhwgWmT59OREQEjRo1ci7ceXh4sHjxYjp16nTdaSi9fFdfWVlZJCUlsWrVKme/qCwFOnnyZCZOnEhZWRkzZ87kzJkztG7dmsTERGcy8/jx41gsFmbPnk16ejp9+/Z1cYvElfr27Uv37t1JSUlh8ODBnD59mrCwMPbu3UthYSFr1qzh/PnzbN68mcWLF7s6XKmCNKfJjVC5UHxtf6g8GV5eXs7s2bP54IMP6NSpEzNmzGDx4sV89NFHZGZmujhyqUo0HonIz3Xs2DGSkpKYMGECYWFhjBgxAi8vL9avX8+FCxd44403iImJ4ZFHHmHYsGEMGDDAOVf91Jwl1dN/6gOvvfYay5cvv+7keFpaGl26dHEmykWsVitBQUGEh4djsVgwm83s2bOH4cOHc//99xMUFERmZiZJSUmEhoZy2223Xff8nDlzmDRpEps2bSIiIsI1jZCbSkFBAXFxcXh6erJ27Vrq1Knj6pDkJqM+JDeC+pFcS4nxaiQ/P58ePXoQHR1NbGwsa9euZfny5YwdO5Zhw4Zx1113YbPZCAwMpGbNmuzduxc/Pz9Xhy1VgM1mo1WrVvj6+rJ06dIf3ZM5adIkUlNTKSkpYc2aNWRlZbF//36aNGnCDz/8QM2aNSkvL+eVV15RuZJqrrCwkIceeohdu3YBEBUVhcVioV27dsDVkvy5ubnUrl2b9u3b88Ybb2gBUH6S5jT5pf71xNSlS5fw8fFxnvCtVJnorEyOZ2VlUV5eTk5ODkuXLmXkyJGuCF+qMI1HIvJzLFy4kCVLlpCbm0taWhovv/wyGRkZ1K1bl23bthETE8OmTZuYO3cuo0ePpl+/fjrtK/+VYRg4HA5nVZvXX38di8VCWFgY3t7evPTSS2RmZtKrVy8XRypVgWEYJCQkkJaWxkcffURISIjzntUhQ4ZQXl5Oeno6c+fOZf/+/Vy6dIlevXpRv359cnNz+eabb9i8eTPvvPMODz74oKubIzeRo0ePcunSJTp27OjqUOQmpT4kN4L6kVRSYryaKC4uZsSIEfj7+ztPYEZERFBYWIjVamXMmDHExsbSuHFjbDYbu3fv1j1BAuB8SbLZbAQHB2MYxnWlQCuT4xMnTmTy5MnO5zIzM7Hb7Zw/f57Q0FD8/f2pW7eu6xoiVcKxY8eIiIhg165dnD17lk6dOrFlyxbCw8MB+OSTTxgxYgSdO3cmLS2NAwcO0KFDBxdHLVWN5jT5pSoTC6Wlpbz99tts27aNkydP4unpiZubG3/+858JDg527hiu/Hx5eTmRkZF8/PHHrF+/nv79+2uzjlxH45GI/DeVG66mTJnCyZMnWbZsGc8++ywHDhxg8+bNznklLCyMXbt2ERISws6dO10dtlQhNpuNU6dOkZWVxZUrVwgICKBBgwbXnda99sqXJUuW8Pzzz3Pp0iXeffddoqOjXRW6VEH5+fkkJyfjcDhISUkhPDwcm81GkyZNGDZsGLNmzQIgNzeXPXv2sGHDBgC8vb0JCwujb9++NG/e3IUtEBEREfltzP/9I3Kzunbh1uFwEBkZSefOnTEMg/DwcDw9PTlx4gTPPPMMixYtwm63M3LkSJo1a0b37t218CvA1budKyoq8PDwYN++fQQHBxMTE+NMjsfFxQGQkJCAh4cH48ePx2w2685MYd26deTl5ZGamuo86WIymfDx8QGgbdu2jBgxgtWrV9OgQQPuuece3nzzTaKiopg5cybp6elYLBa2bt163R3jUj1pTpNfqzLJXVRURFRUFAEBAbRq1YqpU6dy4sQJcnNzmTx5Mg8//DCPPfYY9evXd5attVgsfPzxx2RkZDiT4iIaj0Tk56icf65cuYKXlxc1atTA4XAA0KlTJ/bs2cP+/ftp3749AIGBgURGRhITE8PTTz/N3XffTXx8vCubIFWA1WolNjaWsrIyTp48SZcuXfjiiy/YunUrMTExjBs3joCAAEwmk7PP2e12rFYrGzdupE+fPrqbXq7TqlUr5s+fz9ixY5k3bx5ubm5MmDCB1q1bO5PicPV9vW3btsTHx6vviIiIyC1FNbluUXa7HTc3N86fP8/Fixfx8fEhKiqKoKAgLBYLV65cwWKxAFe/FBuGwcqVK50v6qCXJsH5Am02m7Hb7c7kOEBMTAw5OTk4HA7i4uJYtmwZEydOZPr06a4MWaqQCxcuMHXqVGbNmuUcWxo3bkxQUBBz5szBMAyGDBmCYRh07dqV9u3bs3HjRl544QV8fX3Zv38/bdu2VflI0Zwmv4m7uzslJSX07NkTf39/Xn/9daZNm8ahQ4dwOByMGzeOSZMmsXHjRuc1D4Zh4O7uzqFDh1i9ejUDBw7UorIAGo9E5OexWq2MHTuWBx54gLi4OLZv387999/Pp59+ytdff03nzp1p1qwZs2bNYtKkSfTt25etW7eSkpJCw4YN+e6772jVqpWrmyEuZrVaCQsLw+FwkJqayr59+5g4cSJpaWlkZ2ezd+9e5s2b5/y8u7s7ubm5jBkzhr/85S9Kisu/FRgYyKuvvkpFRQUPP/wwNpuNLVu2AFerBl7r2u8w2iQqIiIitwJlG25BlSW08vLyiIiIYOnSpZw/f54GDRoAcO7cOTw9PfH29gauvmzNnz+fTz75hBYtWrgydKlCKhd+i4qK+P777ykrKwPAw8OD/fv3A9cnx0eOHMmSJUt0R4dw8eJFHA4HiYmJWCwWJk6cyIwZM7DZbAAMHTqUixcvsm3bNnr06MHixYtZvnw5zz//PKdPn+b2229n4cKFLFq0iJEjRyoxXs1pTpMbYf78+fj7+7NixQoCAgLYuHEjf/7znxkzZgzZ2dn07NmTAQMGMG/ePCoqKrDb7QAsWrSIwYMHa1FZAI1HIvLzXL58mXbt2nHkyBH8/f358ssvGT58OAcPHiQyMpLdu3dz5513kpKSQseOHdmxYwcmk4l9+/bh6enJ7Nmz2bFjB82aNXN1U8SFbDYbcXFx3Hnnnbz99tsEBweTmZlJ8+bNSU9Pp2XLlrz11lv85S9/ISsry/lc27ZtKSgoYOjQofr+Iv9RYGAgCxcuJDg4mNtuu43du3cD/KhaW2WJflBfEhERkVuDatPegkwmE0eOHKF79+7ExcXRp08f/P39nX/v6+tLXl4eL7/8MhUVFSxcuJBNmzbpjiBxqlz4PXjwIKNGjaKkpIQLFy4wffp0IiIiaNSokbPsX3x8PIsXL6ZTp07OUn8qEVp9ZWVlkZSUxKpVq+jUqRMjR47E4XCQkJCAYRhMnDiRBx54gM8//5yMjAyOHj1KYmIijzzyCADHjx9n1qxZzJ49m/T0dFq3bu3iFomraU6TG2HPnj306NEDPz8/Bg8ezOnTp+nXrx979+5l2LBhrFmzhqZNm3LPPff85NUNmtMENB6JyH9ntVpp3bo14eHhWCwWzGYze/bsYfjw4ezZs4egoCBWr17NbbfdRmhoKMnJySQnJzufnzNnDpMnT2bTpk00atTIhS0RVzt16hSXL19mwoQJeHh4MGLECLy8vPDz82PIkCEUFRURExNDaGgopaWlwD/L9zdt2tT5e/QdRv6TFi1asHjxYsaOHcv06dNJSUmhR48erg5LRERE5P+Um6E6OLccwzAYPXo0Z86cISMjw/nzymQnwPjx48nOzsYwDMaPH8/AgQNdFa5UUfn5+fTo0YPo6GhiY2NZu3Yty5cvZ+zYsQwbNoy77roLm81GYGAgNWvWZO/evfj5+bk6bHExm81Gq1at8PX1ZenSpXTo0AF3d3csFgsJCQlMmjSJ1NRUSkpKWLNmDVlZWezfv58mTZrwww8/ULNmTcrLy3nllVcICQlxdXOkCtCcJr9VYWEhDz30kLNMelRUFBaLhXbt2gEwePBgcnNzqV27Nu3bt+eNN97QBi/5SRqPROQ/MQyDhIQE0tLS+OijjwgJCaGiogKz2cyQIUMoLy8nPT2duXPnsn//fi5dukSvXr2oX78+ubm5fPPNN2zevJl33nmHBx980NXNERdbuHAhS5YsITc3l7S0NF5++WUyMjKoW7cu27ZtIyYmhk2bNjF37lxGjx5Nv379nIlxkV+qoKCAuLg4PD09Wbt2LXXq1HF1SCIiIiL/Z5QYv0X17NmTNm3aMHfu3OsW6wBKSkrw8vLCarXicDjw9fVViS25TnFxMSNGjMDf35/FixcDEBERQWFhIVarlTFjxhAbG0vjxo2x2Wzs3r2b7t27uzhqcbXKhT+bzUZwcDCGYbBixYofJccnTpzI5MmTnc9lZmZit9s5f/48oaGh+Pv7U7duXdc1RKoczWnyWxw7doyIiAh27drF2bNn6dSpE1u2bCE8PByATz75hBEjRtC5c2fS0tI4cOAAHTp0cHHUUlVpPBKR/yQ/P5/k5GQcDgcpKSmEh4djs9lo0qQJw4YNY9asWQDk5uayZ88eNmzYAIC3tzdhYWH07dtXVSaqucq5ZcqUKZw8eZJly5bx7LPPcuDAATZv3uzcvBcWFsauXbsICQlh586drg5bbgFHjx7l0qVLuh5PREREbnkqpX6L8vf3Jycnx5moqtw5fPr0aTZs2MCjjz56XelHLdbJtafjHA4HkZGRdO7cGcMwCA8Px9PTkxMnTvDMM8+waNEi7HY7I0eOpFmzZnTv3l2n6wSz2UxFRQUeHh7s27eP4OBgYmJinMnxuLg4ABISEvDw8GD8+PGYzWZ69+7t4silqtOcJj/XunXryMvLIzU11XliymQy4ePjA1y9d3PEiBGsXr2aBg0acM899/Dmm28SFRXFzJkzSU9Px2KxsHXr1p8sqS6i8UhE/pNWrVoxf/58xo4dy7x583Bzc2PChAm0bt3amRSHq/NR27ZtiY+P1zghwD/LoF+5cgUvLy9q1KiBw+EAoFOnTuzZs8d5nRlcvR86MjKSmJgYnn76ae6++27n1WYiv8bvfvc7V4cgIiIi8j+hGks3ObvdDkB5eTklJSXOUykDBgzg3LlzzJ49m7KyMufi8ObNm5k3bx7ff/+9y2KWqsdut+Pm5sb58+e5ePEiPj4+REVFERQUhMVi4cqVK1gsFuDqYo9hGKxcudL5og5a+K3uKsces9mM3W53JscBYmJiyMnJweFwEBcXx7Jly5g4cSLTp093ZchSBWlOk9/qwoULTJ06lVmzZjnnqMaNGxMUFMScOXMwDIMhQ4ZgGAZdu3alffv2bNy4kRdeeAFfX1/2799P27ZtVYZUNB6JyK8WGBjIq6++SkVFBQ8//DA2m40tW7YAVyssXeva9ykV86u+rFYrY8eO5YEHHiAuLo7t27dz//338+mnn/L111/TuXNnmjVrxqxZs5g0aRJ9+/Zl69atpKSk0LBhQ7777jtatWrl6maIiIiIiNwUdBTmJlZZYuvgwYO8+OKLHD16lDZt2tCtWzdGjRrFF198wfvvv8/OnTsJDw/n+PHjWCwW0tLStBNUnCr7UV5eHkOGDGHo0KHExsbSoEEDAM6dO4enpyfe3t7A1Zf2+fPnExYWpjJ/AvyzDxUVFWGz2ahRowbe3t54eHg4TzVce3J85MiRVFRU0KhRI1eHLlWI5jT5LS5evIifnx+JiYl4enoyatQoHA4H48ePx8PDg6FDh/Lee++xbds2HnzwQUJCQujduzd2u52oqCi8vb1ZuHAhixYt4rPPPlNivJrTeCQiv1VgYCALFy4kMTERNzc3du/eTUhIyI+qkVx7HYM2GldPly9fJjg4mKZNm+Lv78+XX37J8OHDmTJlCpGRkezevZuhQ4eSkpLC5s2byczMxNfXl3379uHp6cns2bPZsWMHs2fPdnVTRERERERuCrpj/CZ3+PBhQkNDGTx4MPfffz8ff/wxS5Ys4YMPPiA8PJyVK1eyZcsWDh8+TMuWLYmNjSUqKkplr+U6R44cISQkhLi4OB5//HGCgoKcf7do0SJSU1MZNWoUFRUVLFy4kE2bNtGzZ08XRixVxbXJg1GjRlFSUsKFCxeYPn06ERERNGrUCJvNRvv27fHw8GDx4sV06tTJmXTSWCTX0pwmv0ZWVhZJSUmsWrXKOb5YLBYSEhKYPHkyEydOpKysjJkzZ3LmzBlat25NYmKiMzlRmdScPXs26enp9O3b18UtkqpA45GI3AgFBQWMHTsWk8lESkoKPXr0cHVIUoVYrVaCgoIIDw/HYrFgNpvZs2cPw4cP5/777ycoKIjMzEySkpIIDQ3ltttuu+75OXPmMGnSJDZt2kRERIRrGiEiIiIicpNRYvwmce0iW+X/svLycsaMGYO7uztLliwBIDg4mMaNG7Ny5Ur8/PyczxcXF+Pp6YmHh4fzeS3aCVztT6NHj+bMmTNkZGQ4f16Z8AQYP3482dnZGIbB+PHjGThwoKvClSooPz+fHj16EB0dTWxsLGvXrmX58uWMHTuWYcOGcdddd2Gz2QgMDKRmzZrs3bv3uvFJqh/NaXIj2Ww2WrVqha+vL0uXLqVDhw7XJccnTZpEamoqJSUlrFmzhqysLPbv30+TJk344YcfqFmzJuXl5bzyyiuEhIS4ujnyP6bxSET+rxUUFBAXF4enpydr166lTp06rg5JqgDDMEhISCAtLY2PPvqIkJAQKioqMJvNDBkyhPLyctLT05k7dy779+/n0qVL9OrVi/r165Obm8s333zD5s2beeedd3jwwQdd3RwRERERkZuGEuM3AYfDgbu7u/Ouw7KyMmdZ66ioKPr3709cXBwdO3akXr16ZGRk4OPjw/bt2wG0K13+q549e9KmTRvmzp17XUIcoKSkBC8vL6xWKw6HA19fXy38ilNxcTEjRozA39+fxYsXAxAREUFhYSFWq5UxY8YQGxtL48aNsdls7N69m+7du7s4anElzWlyI1UuINtsNoKDgzEMw3ltw7XJ8YkTJzJ58mTnc5mZmdjtds6fP09oaCj+/v7UrVvXdQ0Rl9B4JCL/K0ePHuXSpUt07NjR1aFIFZKfn09ycjIOh4OUlBTCw8Ox2Ww0adKEYcOGMWvWLAByc3PZs2cPGzZsAMDb25uwsDD69u2r681ERERERH4h3TFexVUmKa1WK08++SSFhYX4+vry+OOPM2jQIPz8/Dh16hT33XcfdevWJT09HR8fH4qKisjIyKBly5aEhob+6C4zkWv5+/uTk5PjTDBULhSfPn2aDRs28Oijj+Lv7+/8vBLi1du1p+scDgeRkZF07twZwzAIDw/H09OTEydO8Mwzz7Bo0SLsdjsjR46kWbNmdO/eXWVmqzHNaXKjmc1mKioq8PDwYN++fQQHBxMTE+NMjsfFxQGQkJCAh4cH48ePx2w207t3bxdHLq6m8UhE/pd+97vfuToEqYJatWrF/PnzGTt2LPPmzcPNzY0JEybQunVrZ1IcoG3btrRt25b4+Hi9R4mIiIiI/Eburg5A/r3KBbvLly/Ttm1bLly4wL333suFCxdISkri0KFDDB8+nGnTpnHmzBkyMzPx9fUFYN26daxfv5527dppwU6cKk9ElZeXU1JS4jz5PWDAAM6dO8fs2bMpKytz3v+8efNm5s2bx/fff++ymKVqsdvtuLm5cf78eS5evIiPjw9RUVEEBQVhsVi4cuUKFosFuLrQYxgGK1euxOFwOH+HFnOqJ81pcqNVzmFmsxm73e5MjgPExMSQk5ODw+EgLi6OZcuWMXHiRKZPn+7KkKWK0HgkIiJVRWBgIK+++ioVFRU8/PDD2Gw2tmzZAlytjHOta9+pVPxRREREROTX0WpOFVZ5iqV169aEh4ezfPlyTCYTGRkZREdHk52dTWJiInPmzCE5OZlx48ZRp04d7HY7c+fOJS0tjdDQUFc3Q6qIykXggwcP8uKLL3L06FHatGlDt27dGDVqFF988QXvv/8+O3fuJDw8nOPHj2OxWEhLS9MJBwH+2Yfy8vIYMmQIQ4cOJTY2lgYNGgBw7tw5PD09nWVorVYr8+fPJywsTCX+RHOa3FCV41FRURE2m40aNWrg7e2Nh4cH+/fvp3379tedHB85ciQVFRU0atTI1aFLFaDxSEREqpLAwEAWLlxIYmIibm5u7N69m5CQkB9twLr2yjNtNhYRERER+XV0YrwKMwyDcePGcfbsWeLj450vQaWlpQAcOnSI/Px8oqKi+PTTT8nLyyM7O5uvv/6a9evXEx0drV3E4mQymTh8+DDdunWjfv36TJo0CT8/P5544gm2bt3KjBkzGDVqFLVq1WLFihWcPn2a9PR0Bg0apH4kwNU+dOTIEbp3706vXr3o06fPdSX2fX19ycvL4+WXXyY5OZnnnnuOhg0bKikugOY0uXGu3ej10EMPERERQatWrXjrrbc4deqUMzkOEB8fz2effYbD4SA+Pp7evXurH4nGIxERqXJatGjB4sWLMZvNTJ8+ne3bt7s6JBERERGRW5KboVWdKi0/P5/k5GTsdjsLFizgxIkT9O3bl5CQENq0acOHH35IUVERQ4cOxWw2k5KSgpeXFyaTyblgp53E1c+1dzhX9oPy8nLGjBmDu7s7S5YsASA4OJjGjRuzcuVK/Pz8nM8XFxfj6emJh4eH+pE4GYbB6NGjOXPmDBkZGc6fVyapAMaPH092djaGYTB+/HgGDhzoqnClCtKcJjdKfn4+PXr0IDo6mtjYWNauXcvy5csZO3Ysw4YN46677sJmsxEYGEjNmjXZu3fvdfOciMYjERGpigoKCoiLi8PT05O1a9dSp04dV4ckIiIiInJLUWL8JlBQUMCTTz7JmTNnyMvLY9WqVQwaNAh3d3e++eYbjh07xsyZMzly5Ahr1qyha9eurg5ZXMjhcODu7u68T7ysrMxZ2joqKor+/fsTFxdHx44dqVevHhkZGfj4+Dh3pPfo0cNlsUvV17NnT9q0acPcuXOvS4gDlJSU4OXlhdVqxeFw4Ovrq+SB/IjmNPmtiouLGTFiBP7+/ixevBiAiIgICgsLsVqtjBkzhtjYWBo3bozNZmP37t10797dxVFLVaTxSEREqqKjR49y6dIlOnbs6OpQRERERERuObpj/CYQGBjIggULSExMpGXLljRu3Bh396tV8Bs1akSTJk3o0qULxcXF15U1luqnMlFptVp58sknKSwsxNfXl8cff5xBgwbh5+fHqVOnuO+++6hbty7p6en4+PhQVFRERkYGLVu2JDQ09Ed3mYlU8vf3Jycnh4qKCsxms3MjxunTp9mwYQOPPvrodeOQEuLyrzSnya9xbSUUh8NBZGQknTt3xjAMwsPD8fT05MSJEzzzzDMsWrQIu93OyJEjadasGd27d7/ueZFKGo9ERKQq+t3vfufqEEREREREblm6Y/wmERgYyBtvvEGjRo2YPHkyO3bsAMBsNmO326lVq5YW7Kq5yqT45cuXadu2LRcuXODee+/lwoULJCUlcejQIYYPH860adM4c+YMmZmZ+Pr6ArBu3TrWr19Pu3btlBQXAGfFgfLyckpKSpwnvwcMGMC5c+eYPXs2ZWVlzgTC5s2bmTdvHt9//73LYpabh+Y0+SXsdjtubm6cP3+eixcv4uPjQ1RUFEFBQVgsFq5cuYLFYgGgVatWGIbBypUrcTgczt+hpLj8OxqPRERERERERESqD5VSv8kUFBQwduxYTCYTKSkpKnst17FarQQFBREeHs7y5csxmUxkZGQQHR3N66+/TmJiIvPmzSM5OZmkpCTq1KmD3W5n7ty5pKWlER0d7eomSBVQucni4MGDvPjiixw9epQ2bdrQrVs3Ro0aRUpKCtnZ2fj7+xMeHs7x48exWCykpaUxaNAgV4cvNxHNafLfVI5HeXl5DBkyhKFDhxIbG+tMVM6YMYOsrCzee+896tWrx/z586lbty5hYWE0b97cxdHLzUTjkYiIiIiIiIjIrU8nxm8ygYGBvPrqqxQVFTFt2jQuXrzo6pCkijAMg3HjxnH27Fni4+Oddz+XlpYCcOjQIfLz84mKiuLTTz8lLy+P7Oxsvv76a9avX090dDTaJyMAJpOJw4cP061bN+rXr8+kSZPw8/PjiSeeYOvWrcyYMYNRo0ZRq1YtVqxYwenTp0lPT2fQoEHqQ/KLaE6T/8ZkMnHkyBG6d+9Or1696NOnz3Wnd319fcnLy+Pll18mOTmZ5557joYNGyopLr+YxiMRERERERERkVufTozfpI4ePcqlS5fo2LGjq0ORKiQ/P5/k5GTsdjsLFizgxIkT9O3bl5CQENq0acOHH35IUVERQ4cOxWw2k5KSgpeXFyaTyZnQVLnZ6uXae3cr+0B5eTljxozB3d2dJUuWABAcHEzjxo1ZuXIlfn5+zueLi4vx9PTEw8NDfUh+Nc1p8u8YhsHo0aM5c+YMGRkZzp9XniQHGD9+PNnZ2RiGwfjx4xk4cKCrwpVbgMYjEREREREREZFblxLjIreYgoICnnzySc6cOUNeXh6rVq1i0KBBuLu7880333Ds2DFmzpzJkSNHWLNmDV27dnV1yOIiDocDd3d3533iZWVleHt7AxAVFUX//v2Ji4ujY8eO1KtXj4yMDHx8fNi+fTuAysyKyP9Ez549adOmDXPnzr0uIQ5QUlKCl5cXVqsVh8OBr6+vNumIiIiIiIiIiIjIT1IpdZFbTGBgIAsWLKBOnTq0bNmSxo0b4+5+9Z96o0aNCA8P5/333ycnJ0dJ8WrMbrfj7u6O1WolPj6eiIgI/vjHP5Keng6An58fp06d4r777qNu3bqkp6fj4+NDUVERGRkZ5OXlUVFR4eJWiEh14O/vT05ODhUVFZhMJhwOBwCnT59mxUrpkDsAAAbWSURBVIoVnD9/ntq1a+Pr6wtcTYgrKS4iIiIiIiIiIiL/SolxkVtQYGAgb7zxBo0aNWLy5Mns2LEDALPZjN1up1atWtfd0SrVS+WJy8uXL9O2bVsuXLjAvffey4ULF0hKSuLQoUMMHz6cadOmcebMGTIzM50Jp3Xr1rF+/XratWuH2Wx2cUtE5FZSWb2ivLyckpIS58nvAQMGcO7cOWbPnk1ZWZlzs9fmzZuZN28e33//vctiFhERERERERERkZuHSqmL3MIKCgoYO3YsJpOJlJQUlb4WJ6vVSlBQEOHh4SxfvhyTyURGRgbR0dG8/vrrJCYmMm/ePJKTk0lKSqJOnTrY7Xbmzp1LWloa0dHRrm6CiNxCKjfsHDx4kBdffJGjR4/Spk0bunXrxqhRo0hJSSE7Oxt/f3/Cw8M5fvw4FouFtLQ0Bg0a5OrwRURERERERERE5CagE+Mit7DAwEBeffVVioqKmDZtGhcvXnR1SFIFGIbBuHHjOHv2LPHx8c77ektLSwE4dOgQ+fn5REVF8emnn5KXl0d2djZff/0169evJzo6Gu2pEpEbyWQycfjwYbp160b9+vWZNGkSfn5+PPHEE2zdupUZM2YwatQoatWqxYoVKzh9+jTp6ekMGjRI45GIiIiIiIiIiIj8LDoxLlINHD16lEuXLtGxY0dXhyJVRH5+PsnJydjtdhYsWMCJEyfo27cvISEhtGnThg8//JCioiKGDh2K2WwmJSUFLy8vTCaTMwmlO3xF5NcwDMM5flSOJ+Xl5YwZMwZ3d3eWLFkCQHBwMI0bN2blypX4+fk5ny8uLsbT0xMPDw+NRyIiIiIiIiIiIvKzKTEuIlJNFRQU8OSTT3LmzBny8vJYtWoVgwYNwt3dnW+++YZjx44xc+ZMjhw5wpo1a+jataurQxaRm5zD4cDd3d15n3hZWRne3t4AREVF0b9/f+Li4ujYsSP16tUjIyMDHx8ftm/fDqArQURERERERERERORXUyl1EZFqKjAwkAULFlCnTh1atmxJ48aNcXe/Oi00atSI8PBw3n//fXJycpQUF5HfzG634+7ujtVqJT4+noiICP74xz+Snp4OgJ+fH6dOneK+++6jbt26pKen4+PjQ1FRERkZGeTl5VFRUeHiVoiIiIiIiIiIiMjNSifGRUSqucLCQsaMGYNhGLzwwguEhYUBV5NYlfePi4j8FpXjyeXLl2nfvj2tW7emefPm7N69m6+++oqPP/6YEydO0Lt3b1q0aMHBgwfx8PAA4M033yQ1NZV33nmH0NBQF7dEREREREREREREblZKjIuICAUFBYwdOxaTyURKSorKFYvIDWe1WgkKCiI8PJzly5djMpnIyMggOjqa119/ncTERObNm0dycjJJSUnUqVMHu93O3LlzSUtLIzo62tVNEBERERERERERkZuYSqmLiAiBgYG8+uqrFBUVMW3aNC5evOjqkETkFmIYBuPGjePs2bPEx8c7q1GUlpYCcOjQIfLz84mKiuLTTz8lLy+P7Oxsvv76a9avX090dDTayykiIiIiIiIiIiK/hU6Mi4iI09GjR7l06RIdO3Z0dSgicovJz88nOTkZu93OggULOHHiBH379iUkJIQ2bdrw4YcfUlRUxNChQzGbzaSkpODl5YXJZHImxd3c3FzcChEREREREREREblZKTEuIiIiIv8TBQUFPPnkk5w5c4a8vDxWrVrFoEGDcHd355tvvuHYsWPMnDmTI0eOsGbNGrp27erqkEVEREREREREROQWocS4iIiIiPzPFBQUkJiYyNmzZ1m2bBldunQBoKKiArPZTGlpKcXFxfj7+7s4UhEREREREREREbmVKDEuIiIiIv9ThYWFjBkzBsMweOGFFwgLCwPAbrc77x8XERERERERERERuZGUGBcRERGR/7mCggLGjh2LyWQiJSWFHj16uDokERERERERERERuYUpMS4iIiIiLlFQUEBcXByenp6sXbuWOnXquDokERERERERERERuUUpMS4iIiIiLnP06FEuXbpEx44dXR2KiIiIiIiIiIiI3MKUGBcRERERERERERERERERkVuau6sDEBERERERERERERERERER+b+kxLiIiIiIiIiIiIiIiIiIiNzSlBgXEREREREREREREREREZFbmhLjIiIiIiIiIiIiIiIiIiJyS1NiXEREREREREREREREREREbmlKjIuIiIiIiIiIiIiIiIiIyC1NiXEREREREREREREREREREbmlKTEuIiIiIiIiIiIiIiIiIiK3NCXGRURERERERERERERERETklqbEuIiIiIiIiIiIiIiIiIiI3NL+H4FZpm94wwt8AAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } + "layout": "IPY_MODEL_6a3ffc1cb8764532b215d51cae6e44be" + } + }, + "8bda824cef9c493b83704d511554954c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "983b3ad86d71468c9efc7e01926c70e6": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "9903eb80686c492aa8a5e3190ccc798a": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "9cbf8f18e9dd4cd3acc274ad3f4868ae": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "b014d38bd40740a18eaf90a6d2f69439": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_2001c71b7c0649ad94991dc00c2c1c2b", + "placeholder": "​", + "style": "IPY_MODEL_0b639c296a6e42e883957f4053e08881", + "value": " 17.1M/17.1M [00:06<00:00, 2.10MiB/s]" + } + }, + "b446bbe72b8344dab8c5b637ff3e48bf": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "b7df766690574c09b4942e0d27151171": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b8c4d550a4fb475d8a66c1e5deefb1f2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "c25ebc49169a4fccae65c84ba71b50c7": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_7350acfbe3bd4e1cb4ff49290a6cd58f", + "placeholder": "​", + "style": "IPY_MODEL_5b4d7df8ac4e4a788d7684f47f1d1b76", + "value": " 5183/5183 [00:00<00:00, 45467.14it/s]" + } + }, + "c2c384a4406b4b9f9dfc57779d7246ee": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "c3375ea1a272481babcaece7f79b428e": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "c45d82a40d2c4096b6c00b6c93290add": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "e260dd2233ff479db1471ec42f0b907a": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "e65a397cb2e44371886c3f51362a9bc6": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "e71944737601445a9e8a1f39fe32d445": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "edd9d4c3787f44e2a6d7fe43dec354f2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "ef9546a04f6d47e081b7021376e1fdab": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_f2be4ffe3b984e9989af25faceb3c9fc", + "IPY_MODEL_4cbd2428f91c40d092e1c3bc80171123", + "IPY_MODEL_72b0800f217f4559aea1c0db64d6594c" ], - "source": [ - "plot_search_method_comparison(\n", - " lexical_search_metric_dicts,\n", - " vector_search_metric_dicts,\n", - " hybrid_search_metric_dicts,\n", - " metric_names\n", - ")" - ] + "layout": "IPY_MODEL_983b3ad86d71468c9efc7e01926c70e6" + } + }, + "f22b82b8010a4a79b0b42908966cc89e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_6770f34c4be644cda13221e47d00ca28", + "placeholder": "​", + "style": "IPY_MODEL_c2c384a4406b4b9f9dfc57779d7246ee", + "value": "datasets/scifact.zip: 100%" + } + }, + "f2be4ffe3b984e9989af25faceb3c9fc": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e260dd2233ff479db1471ec42f0b907a", + "placeholder": "​", + "style": "IPY_MODEL_b446bbe72b8344dab8c5b637ff3e48bf", + "value": "100%" + } + }, + "f9596cf74c4b428594a0be76406d96be": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_9903eb80686c492aa8a5e3190ccc798a", + "max": 17948027, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_148567c981e74f1a9b840fb5463f6c1f", + "value": 17948027 + } + }, + "fbf3da22c9954c3ab5995fff682084ba": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } } - ], - "metadata": { - "colab": { - "provenance": [], - "toc_visible": true - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - }, - "widgets": { - "application/vnd.jupyter.widget-state+json": { - "00135b96c1e34abf94352e5d14dfbfc2": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "0b639c296a6e42e883957f4053e08881": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "13eec1cf9f3b4e27995eb7735bbf43aa": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "148567c981e74f1a9b840fb5463f6c1f": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "2001c71b7c0649ad94991dc00c2c1c2b": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "30ccab778b894d8c86359fb850ee76f2": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_b7df766690574c09b4942e0d27151171", - "max": 5183, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_e65a397cb2e44371886c3f51362a9bc6", - "value": 5183 - } - }, - "33ef6c005a52428cb00a9e7ccb0e6b2c": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "350c3f298a7b414c8ab6ea4492fb98c3": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "35b668058eca435a86829f32ca421859": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_33ef6c005a52428cb00a9e7ccb0e6b2c", - "max": 2816079, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_b8c4d550a4fb475d8a66c1e5deefb1f2", - "value": 2816079 - } - }, - "4950b546681b4c8cbec0a9c3acf08c37": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_350c3f298a7b414c8ab6ea4492fb98c3", - "placeholder": "​", - "style": "IPY_MODEL_6275b672934d4cc383cc4c18f3dfe4b7", - "value": "100%" - } - }, - "4cbd2428f91c40d092e1c3bc80171123": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_fbf3da22c9954c3ab5995fff682084ba", - "max": 57638, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_6a61062dbe92469889f767985c4f5b59", - "value": 57638 - } - }, - "51c3a472109243c681898fb32aeda7d7": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_f22b82b8010a4a79b0b42908966cc89e", - "IPY_MODEL_35b668058eca435a86829f32ca421859", - "IPY_MODEL_84d25add023044d68f383b81dacaf462" - ], - "layout": "IPY_MODEL_c3375ea1a272481babcaece7f79b428e" - } - }, - "5b4d7df8ac4e4a788d7684f47f1d1b76": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "5f822791ad0243d99cffb09f57b6257d": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_13eec1cf9f3b4e27995eb7735bbf43aa", - "placeholder": "​", - "style": "IPY_MODEL_8bda824cef9c493b83704d511554954c", - "value": "datasets/fiqa.zip: 100%" - } - }, - "6275b672934d4cc383cc4c18f3dfe4b7": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "6770f34c4be644cda13221e47d00ca28": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "6a3ffc1cb8764532b215d51cae6e44be": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "6a61062dbe92469889f767985c4f5b59": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "72b0800f217f4559aea1c0db64d6594c": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_e71944737601445a9e8a1f39fe32d445", - "placeholder": "​", - "style": "IPY_MODEL_edd9d4c3787f44e2a6d7fe43dec354f2", - "value": " 57638/57638 [00:00<00:00, 91199.90it/s]" - } - }, - "7350acfbe3bd4e1cb4ff49290a6cd58f": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "73cddc3fa8bb4495b335018fae3b063e": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_4950b546681b4c8cbec0a9c3acf08c37", - "IPY_MODEL_30ccab778b894d8c86359fb850ee76f2", - "IPY_MODEL_c25ebc49169a4fccae65c84ba71b50c7" - ], - "layout": "IPY_MODEL_00135b96c1e34abf94352e5d14dfbfc2" - } - }, - "84d25add023044d68f383b81dacaf462": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_c45d82a40d2c4096b6c00b6c93290add", - "placeholder": "​", - "style": "IPY_MODEL_9cbf8f18e9dd4cd3acc274ad3f4868ae", - "value": " 2.69M/2.69M [00:00<00:00, 6.83MiB/s]" - } - }, - "879141a9900d4741985af9ee5f230760": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_5f822791ad0243d99cffb09f57b6257d", - "IPY_MODEL_f9596cf74c4b428594a0be76406d96be", - "IPY_MODEL_b014d38bd40740a18eaf90a6d2f69439" - ], - "layout": "IPY_MODEL_6a3ffc1cb8764532b215d51cae6e44be" - } - }, - "8bda824cef9c493b83704d511554954c": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "983b3ad86d71468c9efc7e01926c70e6": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "9903eb80686c492aa8a5e3190ccc798a": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "9cbf8f18e9dd4cd3acc274ad3f4868ae": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "b014d38bd40740a18eaf90a6d2f69439": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_2001c71b7c0649ad94991dc00c2c1c2b", - "placeholder": "​", - "style": "IPY_MODEL_0b639c296a6e42e883957f4053e08881", - "value": " 17.1M/17.1M [00:06<00:00, 2.10MiB/s]" - } - }, - "b446bbe72b8344dab8c5b637ff3e48bf": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "b7df766690574c09b4942e0d27151171": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "b8c4d550a4fb475d8a66c1e5deefb1f2": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "c25ebc49169a4fccae65c84ba71b50c7": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_7350acfbe3bd4e1cb4ff49290a6cd58f", - "placeholder": "​", - "style": "IPY_MODEL_5b4d7df8ac4e4a788d7684f47f1d1b76", - "value": " 5183/5183 [00:00<00:00, 45467.14it/s]" - } - }, - "c2c384a4406b4b9f9dfc57779d7246ee": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "c3375ea1a272481babcaece7f79b428e": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "c45d82a40d2c4096b6c00b6c93290add": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "e260dd2233ff479db1471ec42f0b907a": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "e65a397cb2e44371886c3f51362a9bc6": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "e71944737601445a9e8a1f39fe32d445": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "edd9d4c3787f44e2a6d7fe43dec354f2": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "ef9546a04f6d47e081b7021376e1fdab": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_f2be4ffe3b984e9989af25faceb3c9fc", - "IPY_MODEL_4cbd2428f91c40d092e1c3bc80171123", - "IPY_MODEL_72b0800f217f4559aea1c0db64d6594c" - ], - "layout": "IPY_MODEL_983b3ad86d71468c9efc7e01926c70e6" - } - }, - "f22b82b8010a4a79b0b42908966cc89e": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_6770f34c4be644cda13221e47d00ca28", - "placeholder": "​", - "style": "IPY_MODEL_c2c384a4406b4b9f9dfc57779d7246ee", - "value": "datasets/scifact.zip: 100%" - } - }, - "f2be4ffe3b984e9989af25faceb3c9fc": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_e260dd2233ff479db1471ec42f0b907a", - "placeholder": "​", - "style": "IPY_MODEL_b446bbe72b8344dab8c5b637ff3e48bf", - "value": "100%" - } - }, - "f9596cf74c4b428594a0be76406d96be": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_9903eb80686c492aa8a5e3190ccc798a", - "max": 17948027, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_148567c981e74f1a9b840fb5463f6c1f", - "value": 17948027 - } - }, - "fbf3da22c9954c3ab5995fff682084ba": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - } - } - } - }, - "nbformat": 4, - "nbformat_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 } diff --git a/notebooks/techniques/quantized_vector_ingestion_with_cohere_and_mongodb.ipynb b/notebooks/techniques/quantized_vector_ingestion_with_cohere_and_mongodb.ipynb index 614709e..60c4305 100644 --- a/notebooks/techniques/quantized_vector_ingestion_with_cohere_and_mongodb.ipynb +++ b/notebooks/techniques/quantized_vector_ingestion_with_cohere_and_mongodb.ipynb @@ -278,9 +278,10 @@ } ], "source": [ + "import getpass\n", "import os\n", + "\n", "import cohere\n", - "import getpass\n", "\n", "COHERE_API_KEY = getpass.getpass(\"Enter Cohere API Key: \")\n", "os.environ[\"COHERE_API_KEY\"] = COHERE_API_KEY" @@ -817,7 +818,6 @@ }, "outputs": [], "source": [ - "import cohere\n", "\n", "# Initialize Cohere Client\n", "co = cohere.Client(COHERE_API_KEY)" @@ -1679,8 +1679,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -1789,6 +1788,7 @@ "source": [ "# Programmatically create vector search index for both colelctions\n", "import time\n", + "\n", "from pymongo.operations import SearchIndexModel\n", "\n", "\n", @@ -1818,7 +1818,7 @@ " return result\n", "\n", " except Exception as e:\n", - " print(f\"Error creating new vector search index '{index_name}': {str(e)}\")\n", + " print(f\"Error creating new vector search index '{index_name}': {e!s}\")\n", " return None" ] }, diff --git a/notebooks/techniques/retrieval_strategies_mongodb_llamaindex.ipynb b/notebooks/techniques/retrieval_strategies_mongodb_llamaindex.ipynb index fa5dc0d..2b7a8d8 100644 --- a/notebooks/techniques/retrieval_strategies_mongodb_llamaindex.ipynb +++ b/notebooks/techniques/retrieval_strategies_mongodb_llamaindex.ipynb @@ -1,2231 +1,2232 @@ { - "cells": [ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/mongodb-developer/GenAI-Showcase/blob/main/notebooks/techniques/retrieval_strategies_mongodb_llamaindex.ipynb)\n", + "\n", + "[![View Article](https://img.shields.io/badge/View%20Article-blue)](https://www.mongodb.com/developer/products/atlas/optimize-relevance-mongodb-llamaindex/?utm_campaign=devrel&utm_source=cross-post&utm_medium=organic_social&utm_content=https%3A%2F%2Fgithub.com%2Fmongodb-developer%2FGenAI-Showcase&utm_term=apoorva.joshi)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Optimizing for relevance using MongoDB and LlamaIndex\n", + "\n", + "In this notebook, we will explore and tune different retrieval options in MongoDB's LlamaIndex integration to get the most relevant results." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "TScxhzzCoi9q" + }, + "source": [ + "## Step 1: Install libraries\n", + "\n", + "- **pymongo**: Python package to interact with MongoDB databases and collections\n", + "

\n", + "- **llama-index**: Python package for the LlamaIndex LLM framework\n", + "

\n", + "- **llama-index-llms-openai**: Python package to use OpenAI models via their LlamaIndex integration \n", + "

\n", + "- **llama-index-vector-stores-mongodb**: Python package for MongoDB’s LlamaIndex integration " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "id": "PqqPt3h_UbeG" + }, + "outputs": [ { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/mongodb-developer/GenAI-Showcase/blob/main/notebooks/techniques/retrieval_strategies_mongodb_llamaindex.ipynb)\n", - "\n", - "[![View Article](https://img.shields.io/badge/View%20Article-blue)](https://www.mongodb.com/developer/products/atlas/optimize-relevance-mongodb-llamaindex/?utm_campaign=devrel&utm_source=cross-post&utm_medium=organic_social&utm_content=https%3A%2F%2Fgithub.com%2Fmongodb-developer%2FGenAI-Showcase&utm_term=apoorva.joshi)\n" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.2\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" + ] + } + ], + "source": [ + "!pip install -qU pymongo llama-index llama-index-llms-openai llama-index-vector-stores-mongodb datasets openai" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 2: Setup prerequisites\n", + "\n", + "- **Set the MongoDB connection string**: Follow the steps [here](https://www.mongodb.com/docs/manual/reference/connection-string/) to get the connection string from the Atlas UI.\n", + "\n", + "- **Set the OpenAI API key**: Steps to obtain an API key as [here](https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Optimizing for relevance using MongoDB and LlamaIndex\n", - "\n", - "In this notebook, we will explore and tune different retrieval options in MongoDB's LlamaIndex integration to get the most relevant results." - ] + "id": "Bs3Safw_Uj00", + "outputId": "5644eb4e-1132-483c-a8ac-b8fce85da591" + }, + "outputs": [], + "source": [ + "import getpass\n", + "import os\n", + "\n", + "from pymongo import MongoClient" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" }, - { - "cell_type": "markdown", - "metadata": { - "id": "TScxhzzCoi9q" - }, - "source": [ - "## Step 1: Install libraries\n", - "\n", - "- **pymongo**: Python package to interact with MongoDB databases and collections\n", - "

\n", - "- **llama-index**: Python package for the LlamaIndex LLM framework\n", - "

\n", - "- **llama-index-llms-openai**: Python package to use OpenAI models via their LlamaIndex integration \n", - "

\n", - "- **llama-index-vector-stores-mongodb**: Python package for MongoDB’s LlamaIndex integration " - ] + "id": "g0GJ9efPUtfA", + "outputId": "1bc3addc-a31e-4a16-9dba-d3486679a419" + }, + "outputs": [], + "source": [ + "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"Enter your OpenAI API key: \")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "id": "qa2Bn-N-pp9a" + }, + "outputs": [], + "source": [ + "MONGODB_URI = getpass.getpass(\"Enter your MongoDB URI: \")\n", + "mongodb_client = MongoClient(\n", + " MONGODB_URI, appname=\"devrel.content.retrieval_strategies_llamaindex\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "rn4FIfvSo33q" + }, + "source": [ + "## Step 3: Load and process the dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "from datasets import load_dataset\n", + "from llama_index.core import Document" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" }, + "id": "jMYkRQwiVag2", + "outputId": "e26784b4-e0fe-48d4-b8e3-9bff5a0c3ad0" + }, + "outputs": [], + "source": [ + "data = load_dataset(\"MongoDB/embedded_movies\", split=\"train\")\n", + "data = pd.DataFrame(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "id": "PqqPt3h_UbeG" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.2\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" - ] - } + "data": { + "text/html": [ + "

\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
plotruntimegenresfullplotdirectorswriterscountriesposterlanguagescasttitlenum_mflix_commentsratedimdbawardstypemetacriticplot_embedding
0Young Pauline is left a lot of money when her ...199.0[Action]Young Pauline is left a lot of money when her ...[Louis J. Gasnier, Donald MacKenzie][Charles W. Goddard (screenplay), Basil Dickey...[USA]https://m.media-amazon.com/images/M/MV5BMzgxOD...[English][Pearl White, Crane Wilbur, Paul Panzer, Edwar...The Perils of Pauline0None{'id': 4465, 'rating': 7.6, 'votes': 744}{'nominations': 0, 'text': '1 win.', 'wins': 1}movieNaN[0.0007293965299999999, -0.026834568000000003,...
1A penniless young man tries to save an heiress...22.0[Comedy, Short, Action]As a penniless man worries about how he will m...[Alfred J. Goulding, Hal Roach][H.M. Walker (titles)][USA]https://m.media-amazon.com/images/M/MV5BNzE1OW...[English][Harold Lloyd, Mildred Davis, 'Snub' Pollard, ...From Hand to Mouth0TV-G{'id': 10146, 'rating': 7.0, 'votes': 639}{'nominations': 1, 'text': '1 nomination.', 'w...movieNaN[-0.022837115, -0.022941574000000003, 0.014937...
2Michael \"Beau\" Geste leaves England in disgrac...101.0[Action, Adventure, Drama]Michael \"Beau\" Geste leaves England in disgrac...[Herbert Brenon][Herbert Brenon (adaptation), John Russell (ad...[USA]None[English][Ronald Colman, Neil Hamilton, Ralph Forbes, A...Beau Geste0None{'id': 16634, 'rating': 6.9, 'votes': 222}{'nominations': 0, 'text': '1 win.', 'wins': 1}movieNaN[0.00023330492999999998, -0.028511643000000003...
3Seeking revenge, an athletic young man joins t...88.0[Adventure, Action]A nobleman vows to avenge the death of his fat...[Albert Parker][Douglas Fairbanks (story), Jack Cunningham (a...[USA]https://m.media-amazon.com/images/M/MV5BMzU0ND...None[Billie Dove, Tempe Pigott, Donald Crisp, Sam ...The Black Pirate1None{'id': 16654, 'rating': 7.2, 'votes': 1146}{'nominations': 0, 'text': '1 win.', 'wins': 1}movieNaN[-0.005927917, -0.033394486, 0.0015323418, -0....
4An irresponsible young millionaire changes his...58.0[Action, Comedy, Romance]The Uptown Boy, J. Harold Manners (Lloyd) is a...[Sam Taylor][Ted Wilde (story), John Grey (story), Clyde B...[USA]https://m.media-amazon.com/images/M/MV5BMTcxMT...[English][Harold Lloyd, Jobyna Ralston, Noah Young, Jim...For Heaven's Sake0PASSED{'id': 16895, 'rating': 7.6, 'votes': 918}{'nominations': 1, 'text': '1 nomination.', 'w...movieNaN[-0.0059373598, -0.026604708, -0.0070914757000...
\n", + "
" ], - "source": [ - "!pip install -qU pymongo llama-index llama-index-llms-openai llama-index-vector-stores-mongodb datasets openai" + "text/plain": [ + " plot runtime \\\n", + "0 Young Pauline is left a lot of money when her ... 199.0 \n", + "1 A penniless young man tries to save an heiress... 22.0 \n", + "2 Michael \"Beau\" Geste leaves England in disgrac... 101.0 \n", + "3 Seeking revenge, an athletic young man joins t... 88.0 \n", + "4 An irresponsible young millionaire changes his... 58.0 \n", + "\n", + " genres \\\n", + "0 [Action] \n", + "1 [Comedy, Short, Action] \n", + "2 [Action, Adventure, Drama] \n", + "3 [Adventure, Action] \n", + "4 [Action, Comedy, Romance] \n", + "\n", + " fullplot \\\n", + "0 Young Pauline is left a lot of money when her ... \n", + "1 As a penniless man worries about how he will m... \n", + "2 Michael \"Beau\" Geste leaves England in disgrac... \n", + "3 A nobleman vows to avenge the death of his fat... \n", + "4 The Uptown Boy, J. Harold Manners (Lloyd) is a... \n", + "\n", + " directors \\\n", + "0 [Louis J. Gasnier, Donald MacKenzie] \n", + "1 [Alfred J. Goulding, Hal Roach] \n", + "2 [Herbert Brenon] \n", + "3 [Albert Parker] \n", + "4 [Sam Taylor] \n", + "\n", + " writers countries \\\n", + "0 [Charles W. Goddard (screenplay), Basil Dickey... [USA] \n", + "1 [H.M. Walker (titles)] [USA] \n", + "2 [Herbert Brenon (adaptation), John Russell (ad... [USA] \n", + "3 [Douglas Fairbanks (story), Jack Cunningham (a... [USA] \n", + "4 [Ted Wilde (story), John Grey (story), Clyde B... [USA] \n", + "\n", + " poster languages \\\n", + "0 https://m.media-amazon.com/images/M/MV5BMzgxOD... [English] \n", + "1 https://m.media-amazon.com/images/M/MV5BNzE1OW... [English] \n", + "2 None [English] \n", + "3 https://m.media-amazon.com/images/M/MV5BMzU0ND... None \n", + "4 https://m.media-amazon.com/images/M/MV5BMTcxMT... [English] \n", + "\n", + " cast title \\\n", + "0 [Pearl White, Crane Wilbur, Paul Panzer, Edwar... The Perils of Pauline \n", + "1 [Harold Lloyd, Mildred Davis, 'Snub' Pollard, ... From Hand to Mouth \n", + "2 [Ronald Colman, Neil Hamilton, Ralph Forbes, A... Beau Geste \n", + "3 [Billie Dove, Tempe Pigott, Donald Crisp, Sam ... The Black Pirate \n", + "4 [Harold Lloyd, Jobyna Ralston, Noah Young, Jim... For Heaven's Sake \n", + "\n", + " num_mflix_comments rated imdb \\\n", + "0 0 None {'id': 4465, 'rating': 7.6, 'votes': 744} \n", + "1 0 TV-G {'id': 10146, 'rating': 7.0, 'votes': 639} \n", + "2 0 None {'id': 16634, 'rating': 6.9, 'votes': 222} \n", + "3 1 None {'id': 16654, 'rating': 7.2, 'votes': 1146} \n", + "4 0 PASSED {'id': 16895, 'rating': 7.6, 'votes': 918} \n", + "\n", + " awards type metacritic \\\n", + "0 {'nominations': 0, 'text': '1 win.', 'wins': 1} movie NaN \n", + "1 {'nominations': 1, 'text': '1 nomination.', 'w... movie NaN \n", + "2 {'nominations': 0, 'text': '1 win.', 'wins': 1} movie NaN \n", + "3 {'nominations': 0, 'text': '1 win.', 'wins': 1} movie NaN \n", + "4 {'nominations': 1, 'text': '1 nomination.', 'w... movie NaN \n", + "\n", + " plot_embedding \n", + "0 [0.0007293965299999999, -0.026834568000000003,... \n", + "1 [-0.022837115, -0.022941574000000003, 0.014937... \n", + "2 [0.00023330492999999998, -0.028511643000000003... \n", + "3 [-0.005927917, -0.033394486, 0.0015323418, -0.... \n", + "4 [-0.0059373598, -0.026604708, -0.0070914757000... " ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step 2: Setup prerequisites\n", - "\n", - "- **Set the MongoDB connection string**: Follow the steps [here](https://www.mongodb.com/docs/manual/reference/connection-string/) to get the connection string from the Atlas UI.\n", - "\n", - "- **Set the OpenAI API key**: Steps to obtain an API key as [here](https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key)" - ] - }, + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "# Fill Nones in the dataframe\n", + "data = data.fillna({\"genres\": \"[]\", \"languages\": \"[]\", \"cast\": \"[]\", \"imdb\": \"{}\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "documents = []\n", + "\n", + "for _, row in data.iterrows():\n", + " # Extract required fields\n", + " title = row[\"title\"]\n", + " rating = row[\"imdb\"].get(\"rating\", 0)\n", + " languages = row[\"languages\"]\n", + " cast = row[\"cast\"]\n", + " genres = row[\"genres\"]\n", + " # Create the metadata attribute\n", + " metadata = {\"title\": title, \"rating\": rating, \"languages\": languages}\n", + " # Create the text attribute\n", + " text = f\"Title: {title}\\nPlot: {row['fullplot']}\\nCast: {', '.join(item for item in cast)}\\nGenres: {', '.join(item for item in genres)}\\nLanguages: {', '.join(item for item in languages)}\\nRating: {rating}\"\n", + " documents.append(Document(text=text, metadata=metadata))" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "Bs3Safw_Uj00", - "outputId": "5644eb4e-1132-483c-a8ac-b8fce85da591" - }, - "outputs": [], - "source": [ - "import os\n", - "import getpass\n", - "from pymongo import MongoClient" - ] - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Title: The Perils of Pauline\n", + "Plot: Young Pauline is left a lot of money when her wealthy uncle dies. However, her uncle's secretary has been named as her guardian until she marries, at which time she will officially take possession of her inheritance. Meanwhile, her \"guardian\" and his confederates constantly come up with schemes to get rid of Pauline so that he can get his hands on the money himself.\n", + "Cast: Pearl White, Crane Wilbur, Paul Panzer, Edward Josè\n", + "Genres: Action\n", + "Languages: English\n", + "Rating: 7.6\n" + ] + } + ], + "source": [ + "print(documents[0].text)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "g0GJ9efPUtfA", - "outputId": "1bc3addc-a31e-4a16-9dba-d3486679a419" - }, - "outputs": [], - "source": [ - "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"Enter your OpenAI API key: \")" - ] - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "{'title': 'The Perils of Pauline', 'rating': 7.6, 'languages': ['English']}\n" + ] + } + ], + "source": [ + "print(documents[0].metadata)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 4: Create MongoDB Atlas vector store" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "from llama_index.core import StorageContext, VectorStoreIndex\n", + "from llama_index.core.settings import Settings\n", + "from llama_index.embeddings.openai import OpenAIEmbedding\n", + "from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch\n", + "from pymongo.errors import OperationFailure\n", + "from pymongo.operations import SearchIndexModel" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "Settings.embed_model = OpenAIEmbedding(model=\"text-embedding-3-small\")" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "VS_INDEX_NAME = \"vector_index\"\n", + "FTS_INDEX_NAME = \"fts_index\"\n", + "DB_NAME = \"llamaindex\"\n", + "COLLECTION_NAME = \"hybrid_search\"\n", + "collection = mongodb_client[DB_NAME][COLLECTION_NAME]" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "vector_store = MongoDBAtlasVectorSearch(\n", + " mongodb_client,\n", + " db_name=DB_NAME,\n", + " collection_name=COLLECTION_NAME,\n", + " vector_index_name=VS_INDEX_NAME,\n", + " fulltext_index_name=FTS_INDEX_NAME,\n", + " embedding_key=\"embedding\",\n", + " text_key=\"text\",\n", + ")\n", + "# If the collection has documents with embeddings already, create the vector store index from the vector store\n", + "if collection.count_documents({}) > 0:\n", + " vector_store_index = VectorStoreIndex.from_vector_store(vector_store)\n", + "# If the collection does not have documents, embed and ingest them into the vector store\n", + "else:\n", + " vector_store_context = StorageContext.from_defaults(vector_store=vector_store)\n", + " vector_store_index = VectorStoreIndex.from_documents(\n", + " documents, storage_context=vector_store_context, show_progress=True\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 5: Create Atlas Search indexes" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "vs_model = SearchIndexModel(\n", + " definition={\n", + " \"fields\": [\n", + " {\n", + " \"type\": \"vector\",\n", + " \"path\": \"embedding\",\n", + " \"numDimensions\": 1536,\n", + " \"similarity\": \"cosine\",\n", + " },\n", + " {\"type\": \"filter\", \"path\": \"metadata.rating\"},\n", + " {\"type\": \"filter\", \"path\": \"metadata.languages\"},\n", + " ]\n", + " },\n", + " name=VS_INDEX_NAME,\n", + " type=\"vectorSearch\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "fts_model = SearchIndexModel(\n", + " definition={\"mappings\": {\"dynamic\": False, \"fields\": {\"text\": {\"type\": \"string\"}}}},\n", + " name=FTS_INDEX_NAME,\n", + " type=\"search\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "id": "qa2Bn-N-pp9a" - }, - "outputs": [], - "source": [ - "MONGODB_URI = getpass.getpass(\"Enter your MongoDB URI: \")\n", - "mongodb_client = MongoClient(\n", - " MONGODB_URI, appname=\"devrel.content.retrieval_strategies_llamaindex\"\n", - ")" - ] - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Duplicate index found for model . Skipping index creation.\n", + "Duplicate index found for model . Skipping index creation.\n" + ] + } + ], + "source": [ + "for model in [vs_model, fts_model]:\n", + " try:\n", + " collection.create_search_index(model=model)\n", + " except OperationFailure:\n", + " print(f\"Duplicate index found for model {model}. Skipping index creation.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 6: Get movie recommendations" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "def get_recommendations(query: str, mode: str, **kwargs) -> None:\n", + " \"\"\"\n", + " Get movie recommendations\n", + "\n", + " Args:\n", + " query (str): User query\n", + " mode (str): Retrieval mode. One of (default, text_search, hybrid)\n", + " \"\"\"\n", + " query_engine = vector_store_index.as_query_engine(\n", + " similarity_top_k=5, vector_store_query_mode=mode, **kwargs\n", + " )\n", + " response = query_engine.query(query)\n", + " nodes = response.source_nodes\n", + " for node in nodes:\n", + " title = node.metadata[\"title\"]\n", + " rating = node.metadata[\"rating\"]\n", + " score = node.score\n", + " print(f\"Title: {title} | Rating: {rating} | Relevance Score: {score}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Full-text search" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ { - "cell_type": "markdown", - "metadata": { - "id": "rn4FIfvSo33q" - }, - "source": [ - "## Step 3: Load and process the dataset" - ] - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Title: Hellboy II: The Golden Army | Rating: 7.0 | Relevance Score: 5.93734884262085\n", + "Title: The Matrix Revolutions | Rating: 6.7 | Relevance Score: 4.574477195739746\n", + "Title: The Matrix | Rating: 8.7 | Relevance Score: 4.387373924255371\n", + "Title: Go with Peace Jamil | Rating: 6.9 | Relevance Score: 3.5394840240478516\n", + "Title: Terminator Salvation | Rating: 6.7 | Relevance Score: 3.3378987312316895\n" + ] + } + ], + "source": [ + "get_recommendations(\n", + " query=\"Action movies about humans fighting machines\",\n", + " mode=\"text_search\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Vector search" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "from datasets import load_dataset\n", - "import pandas as pd\n", - "from llama_index.core import Document" - ] - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Title: Death Machine | Rating: 5.7 | Relevance Score: 0.7407287359237671\n", + "Title: Real Steel | Rating: 7.1 | Relevance Score: 0.7364246845245361\n", + "Title: Soldier | Rating: 5.9 | Relevance Score: 0.7282171249389648\n", + "Title: Terminator 3: Rise of the Machines | Rating: 6.4 | Relevance Score: 0.7266112565994263\n", + "Title: Last Action Hero | Rating: 6.2 | Relevance Score: 0.7250100374221802\n" + ] + } + ], + "source": [ + "get_recommendations(\n", + " query=\"Action movies about humans fighting machines\", mode=\"default\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Hybrid search" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "jMYkRQwiVag2", - "outputId": "e26784b4-e0fe-48d4-b8e3-9bff5a0c3ad0" - }, - "outputs": [], - "source": [ - "data = load_dataset(\"MongoDB/embedded_movies\", split=\"train\")\n", - "data = pd.DataFrame(data)" - ] - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Title: Hellboy II: The Golden Army | Rating: 7.0 | Relevance Score: 0.5\n", + "Title: Death Machine | Rating: 5.7 | Relevance Score: 0.5\n", + "Title: The Matrix Revolutions | Rating: 6.7 | Relevance Score: 0.25\n", + "Title: Real Steel | Rating: 7.1 | Relevance Score: 0.25\n", + "Title: Soldier | Rating: 5.9 | Relevance Score: 0.16666666666666666\n" + ] + } + ], + "source": [ + "# Vector and full-text search weighted equal by default\n", + "get_recommendations(query=\"Action movies about humans fighting machines\", mode=\"hybrid\")" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
plotruntimegenresfullplotdirectorswriterscountriesposterlanguagescasttitlenum_mflix_commentsratedimdbawardstypemetacriticplot_embedding
0Young Pauline is left a lot of money when her ...199.0[Action]Young Pauline is left a lot of money when her ...[Louis J. Gasnier, Donald MacKenzie][Charles W. Goddard (screenplay), Basil Dickey...[USA]https://m.media-amazon.com/images/M/MV5BMzgxOD...[English][Pearl White, Crane Wilbur, Paul Panzer, Edwar...The Perils of Pauline0None{'id': 4465, 'rating': 7.6, 'votes': 744}{'nominations': 0, 'text': '1 win.', 'wins': 1}movieNaN[0.0007293965299999999, -0.026834568000000003,...
1A penniless young man tries to save an heiress...22.0[Comedy, Short, Action]As a penniless man worries about how he will m...[Alfred J. Goulding, Hal Roach][H.M. Walker (titles)][USA]https://m.media-amazon.com/images/M/MV5BNzE1OW...[English][Harold Lloyd, Mildred Davis, 'Snub' Pollard, ...From Hand to Mouth0TV-G{'id': 10146, 'rating': 7.0, 'votes': 639}{'nominations': 1, 'text': '1 nomination.', 'w...movieNaN[-0.022837115, -0.022941574000000003, 0.014937...
2Michael \"Beau\" Geste leaves England in disgrac...101.0[Action, Adventure, Drama]Michael \"Beau\" Geste leaves England in disgrac...[Herbert Brenon][Herbert Brenon (adaptation), John Russell (ad...[USA]None[English][Ronald Colman, Neil Hamilton, Ralph Forbes, A...Beau Geste0None{'id': 16634, 'rating': 6.9, 'votes': 222}{'nominations': 0, 'text': '1 win.', 'wins': 1}movieNaN[0.00023330492999999998, -0.028511643000000003...
3Seeking revenge, an athletic young man joins t...88.0[Adventure, Action]A nobleman vows to avenge the death of his fat...[Albert Parker][Douglas Fairbanks (story), Jack Cunningham (a...[USA]https://m.media-amazon.com/images/M/MV5BMzU0ND...None[Billie Dove, Tempe Pigott, Donald Crisp, Sam ...The Black Pirate1None{'id': 16654, 'rating': 7.2, 'votes': 1146}{'nominations': 0, 'text': '1 win.', 'wins': 1}movieNaN[-0.005927917, -0.033394486, 0.0015323418, -0....
4An irresponsible young millionaire changes his...58.0[Action, Comedy, Romance]The Uptown Boy, J. Harold Manners (Lloyd) is a...[Sam Taylor][Ted Wilde (story), John Grey (story), Clyde B...[USA]https://m.media-amazon.com/images/M/MV5BMTcxMT...[English][Harold Lloyd, Jobyna Ralston, Noah Young, Jim...For Heaven's Sake0PASSED{'id': 16895, 'rating': 7.6, 'votes': 918}{'nominations': 1, 'text': '1 nomination.', 'w...movieNaN[-0.0059373598, -0.026604708, -0.0070914757000...
\n", - "
" - ], - "text/plain": [ - " plot runtime \\\n", - "0 Young Pauline is left a lot of money when her ... 199.0 \n", - "1 A penniless young man tries to save an heiress... 22.0 \n", - "2 Michael \"Beau\" Geste leaves England in disgrac... 101.0 \n", - "3 Seeking revenge, an athletic young man joins t... 88.0 \n", - "4 An irresponsible young millionaire changes his... 58.0 \n", - "\n", - " genres \\\n", - "0 [Action] \n", - "1 [Comedy, Short, Action] \n", - "2 [Action, Adventure, Drama] \n", - "3 [Adventure, Action] \n", - "4 [Action, Comedy, Romance] \n", - "\n", - " fullplot \\\n", - "0 Young Pauline is left a lot of money when her ... \n", - "1 As a penniless man worries about how he will m... \n", - "2 Michael \"Beau\" Geste leaves England in disgrac... \n", - "3 A nobleman vows to avenge the death of his fat... \n", - "4 The Uptown Boy, J. Harold Manners (Lloyd) is a... \n", - "\n", - " directors \\\n", - "0 [Louis J. Gasnier, Donald MacKenzie] \n", - "1 [Alfred J. Goulding, Hal Roach] \n", - "2 [Herbert Brenon] \n", - "3 [Albert Parker] \n", - "4 [Sam Taylor] \n", - "\n", - " writers countries \\\n", - "0 [Charles W. Goddard (screenplay), Basil Dickey... [USA] \n", - "1 [H.M. Walker (titles)] [USA] \n", - "2 [Herbert Brenon (adaptation), John Russell (ad... [USA] \n", - "3 [Douglas Fairbanks (story), Jack Cunningham (a... [USA] \n", - "4 [Ted Wilde (story), John Grey (story), Clyde B... [USA] \n", - "\n", - " poster languages \\\n", - "0 https://m.media-amazon.com/images/M/MV5BMzgxOD... [English] \n", - "1 https://m.media-amazon.com/images/M/MV5BNzE1OW... [English] \n", - "2 None [English] \n", - "3 https://m.media-amazon.com/images/M/MV5BMzU0ND... None \n", - "4 https://m.media-amazon.com/images/M/MV5BMTcxMT... [English] \n", - "\n", - " cast title \\\n", - "0 [Pearl White, Crane Wilbur, Paul Panzer, Edwar... The Perils of Pauline \n", - "1 [Harold Lloyd, Mildred Davis, 'Snub' Pollard, ... From Hand to Mouth \n", - "2 [Ronald Colman, Neil Hamilton, Ralph Forbes, A... Beau Geste \n", - "3 [Billie Dove, Tempe Pigott, Donald Crisp, Sam ... The Black Pirate \n", - "4 [Harold Lloyd, Jobyna Ralston, Noah Young, Jim... For Heaven's Sake \n", - "\n", - " num_mflix_comments rated imdb \\\n", - "0 0 None {'id': 4465, 'rating': 7.6, 'votes': 744} \n", - "1 0 TV-G {'id': 10146, 'rating': 7.0, 'votes': 639} \n", - "2 0 None {'id': 16634, 'rating': 6.9, 'votes': 222} \n", - "3 1 None {'id': 16654, 'rating': 7.2, 'votes': 1146} \n", - "4 0 PASSED {'id': 16895, 'rating': 7.6, 'votes': 918} \n", - "\n", - " awards type metacritic \\\n", - "0 {'nominations': 0, 'text': '1 win.', 'wins': 1} movie NaN \n", - "1 {'nominations': 1, 'text': '1 nomination.', 'w... movie NaN \n", - "2 {'nominations': 0, 'text': '1 win.', 'wins': 1} movie NaN \n", - "3 {'nominations': 0, 'text': '1 win.', 'wins': 1} movie NaN \n", - "4 {'nominations': 1, 'text': '1 nomination.', 'w... movie NaN \n", - "\n", - " plot_embedding \n", - "0 [0.0007293965299999999, -0.026834568000000003,... \n", - "1 [-0.022837115, -0.022941574000000003, 0.014937... \n", - "2 [0.00023330492999999998, -0.028511643000000003... \n", - "3 [-0.005927917, -0.033394486, 0.0015323418, -0.... \n", - "4 [-0.0059373598, -0.026604708, -0.0070914757000... " - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "data.head()" - ] - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Title: Death Machine | Rating: 5.7 | Relevance Score: 0.7\n", + "Title: Real Steel | Rating: 7.1 | Relevance Score: 0.35\n", + "Title: Hellboy II: The Golden Army | Rating: 7.0 | Relevance Score: 0.30000000000000004\n", + "Title: Soldier | Rating: 5.9 | Relevance Score: 0.2333333333333333\n", + "Title: Terminator 3: Rise of the Machines | Rating: 6.4 | Relevance Score: 0.175\n" + ] + } + ], + "source": [ + "# Higher alpha, vector search dominates\n", + "get_recommendations(\n", + " query=\"Action movies about humans fighting machines\",\n", + " mode=\"hybrid\",\n", + " alpha=0.7,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [], - "source": [ - "# Fill Nones in the dataframe\n", - "data = data.fillna({\"genres\": \"[]\", \"languages\": \"[]\", \"cast\": \"[]\", \"imdb\": \"{}\"})" - ] - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Title: Hellboy II: The Golden Army | Rating: 7.0 | Relevance Score: 0.7\n", + "Title: The Matrix Revolutions | Rating: 6.7 | Relevance Score: 0.35\n", + "Title: Death Machine | Rating: 5.7 | Relevance Score: 0.3\n", + "Title: The Matrix | Rating: 8.7 | Relevance Score: 0.2333333333333333\n", + "Title: Go with Peace Jamil | Rating: 6.9 | Relevance Score: 0.175\n" + ] + } + ], + "source": [ + "# Lower alpha, full-text search dominates\n", + "get_recommendations(\n", + " query=\"Action movies about humans fighting machines\",\n", + " mode=\"hybrid\",\n", + " alpha=0.3,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Combining metadata filters with search" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [], + "source": [ + "from llama_index.core.vector_stores import (\n", + " FilterCondition,\n", + " FilterOperator,\n", + " MetadataFilter,\n", + " MetadataFilters,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [], + "source": [ + "filters = MetadataFilters(\n", + " filters=[\n", + " MetadataFilter(key=\"metadata.rating\", value=7, operator=FilterOperator.GT),\n", + " MetadataFilter(\n", + " key=\"metadata.languages\", value=\"English\", operator=FilterOperator.EQ\n", + " ),\n", + " ],\n", + " condition=FilterCondition.AND,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [], - "source": [ - "documents = []\n", - "\n", - "for _, row in data.iterrows():\n", - " # Extract required fields\n", - " title = row[\"title\"]\n", - " rating = row[\"imdb\"].get(\"rating\", 0)\n", - " languages = row[\"languages\"]\n", - " cast = row[\"cast\"]\n", - " genres = row[\"genres\"]\n", - " # Create the metadata attribute\n", - " metadata = {\"title\": title, \"rating\": rating, \"languages\": languages}\n", - " # Create the text attribute\n", - " text = f\"Title: {title}\\nPlot: {row['fullplot']}\\nCast: {', '.join(item for item in cast)}\\nGenres: {', '.join(item for item in genres)}\\nLanguages: {', '.join(item for item in languages)}\\nRating: {rating}\"\n", - " documents.append(Document(text=text, metadata=metadata))" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "Title: Real Steel | Rating: 7.1 | Relevance Score: 0.7\n", + "Title: T2 3-D: Battle Across Time | Rating: 7.8 | Relevance Score: 0.35\n", + "Title: The Matrix | Rating: 8.7 | Relevance Score: 0.30000000000000004\n", + "Title: Predator | Rating: 7.8 | Relevance Score: 0.2333333333333333\n", + "Title: Transformers | Rating: 7.1 | Relevance Score: 0.175\n" + ] + } + ], + "source": [ + "get_recommendations(\n", + " query=\"Action movies about humans fighting machines\",\n", + " mode=\"hybrid\",\n", + " alpha=0.7,\n", + " filters=filters,\n", + ")" + ] + } + ], + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "kernelspec": { + "display_name": "Python 3", + "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.12.1" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "00135b96c1e34abf94352e5d14dfbfc2": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Title: The Perils of Pauline\n", - "Plot: Young Pauline is left a lot of money when her wealthy uncle dies. However, her uncle's secretary has been named as her guardian until she marries, at which time she will officially take possession of her inheritance. Meanwhile, her \"guardian\" and his confederates constantly come up with schemes to get rid of Pauline so that he can get his hands on the money himself.\n", - "Cast: Pearl White, Crane Wilbur, Paul Panzer, Edward Josè\n", - "Genres: Action\n", - "Languages: English\n", - "Rating: 7.6\n" - ] - } - ], - "source": [ - "print(documents[0].text)" - ] + "0b639c296a6e42e883957f4053e08881": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'title': 'The Perils of Pauline', 'rating': 7.6, 'languages': ['English']}\n" - ] - } - ], - "source": [ - "print(documents[0].metadata)" - ] + "13eec1cf9f3b4e27995eb7735bbf43aa": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step 4: Create MongoDB Atlas vector store" - ] + "148567c981e74f1a9b840fb5463f6c1f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [], - "source": [ - "from llama_index.embeddings.openai import OpenAIEmbedding\n", - "from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch\n", - "from llama_index.core.settings import Settings\n", - "from llama_index.core import VectorStoreIndex, StorageContext\n", - "from pymongo.operations import SearchIndexModel\n", - "from pymongo.errors import OperationFailure" - ] + "2001c71b7c0649ad94991dc00c2c1c2b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [], - "source": [ - "Settings.embed_model = OpenAIEmbedding(model=\"text-embedding-3-small\")" - ] + "30ccab778b894d8c86359fb850ee76f2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b7df766690574c09b4942e0d27151171", + "max": 5183, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_e65a397cb2e44371886c3f51362a9bc6", + "value": 5183 + } }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "VS_INDEX_NAME = \"vector_index\"\n", - "FTS_INDEX_NAME = \"fts_index\"\n", - "DB_NAME = \"llamaindex\"\n", - "COLLECTION_NAME = \"hybrid_search\"\n", - "collection = mongodb_client[DB_NAME][COLLECTION_NAME]" - ] + "33ef6c005a52428cb00a9e7ccb0e6b2c": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [], - "source": [ - "vector_store = MongoDBAtlasVectorSearch(\n", - " mongodb_client,\n", - " db_name=DB_NAME,\n", - " collection_name=COLLECTION_NAME,\n", - " vector_index_name=VS_INDEX_NAME,\n", - " fulltext_index_name=FTS_INDEX_NAME,\n", - " embedding_key=\"embedding\",\n", - " text_key=\"text\",\n", - ")\n", - "# If the collection has documents with embeddings already, create the vector store index from the vector store\n", - "if collection.count_documents({}) > 0:\n", - " vector_store_index = VectorStoreIndex.from_vector_store(vector_store)\n", - "# If the collection does not have documents, embed and ingest them into the vector store\n", - "else:\n", - " vector_store_context = StorageContext.from_defaults(vector_store=vector_store)\n", - " vector_store_index = VectorStoreIndex.from_documents(\n", - " documents, storage_context=vector_store_context, show_progress=True\n", - " )" - ] + "350c3f298a7b414c8ab6ea4492fb98c3": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step 5: Create Atlas Search indexes" - ] + "35b668058eca435a86829f32ca421859": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_33ef6c005a52428cb00a9e7ccb0e6b2c", + "max": 2816079, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_b8c4d550a4fb475d8a66c1e5deefb1f2", + "value": 2816079 + } }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [], - "source": [ - "vs_model = SearchIndexModel(\n", - " definition={\n", - " \"fields\": [\n", - " {\n", - " \"type\": \"vector\",\n", - " \"path\": \"embedding\",\n", - " \"numDimensions\": 1536,\n", - " \"similarity\": \"cosine\",\n", - " },\n", - " {\"type\": \"filter\", \"path\": \"metadata.rating\"},\n", - " {\"type\": \"filter\", \"path\": \"metadata.languages\"},\n", - " ]\n", - " },\n", - " name=VS_INDEX_NAME,\n", - " type=\"vectorSearch\",\n", - ")" - ] + "4950b546681b4c8cbec0a9c3acf08c37": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_350c3f298a7b414c8ab6ea4492fb98c3", + "placeholder": "​", + "style": "IPY_MODEL_6275b672934d4cc383cc4c18f3dfe4b7", + "value": "100%" + } }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "fts_model = SearchIndexModel(\n", - " definition={\"mappings\": {\"dynamic\": False, \"fields\": {\"text\": {\"type\": \"string\"}}}},\n", - " name=FTS_INDEX_NAME,\n", - " type=\"search\",\n", - ")" - ] + "4cbd2428f91c40d092e1c3bc80171123": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_fbf3da22c9954c3ab5995fff682084ba", + "max": 57638, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_6a61062dbe92469889f767985c4f5b59", + "value": 57638 + } }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Duplicate index found for model . Skipping index creation.\n", - "Duplicate index found for model . Skipping index creation.\n" - ] - } + "51c3a472109243c681898fb32aeda7d7": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_f22b82b8010a4a79b0b42908966cc89e", + "IPY_MODEL_35b668058eca435a86829f32ca421859", + "IPY_MODEL_84d25add023044d68f383b81dacaf462" ], - "source": [ - "for model in [vs_model, fts_model]:\n", - " try:\n", - " collection.create_search_index(model=model)\n", - " except OperationFailure:\n", - " print(f\"Duplicate index found for model {model}. Skipping index creation.\")" - ] + "layout": "IPY_MODEL_c3375ea1a272481babcaece7f79b428e" + } }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step 6: Get movie recommendations" - ] + "5b4d7df8ac4e4a788d7684f47f1d1b76": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "def get_recommendations(query: str, mode: str, **kwargs) -> None:\n", - " \"\"\"\n", - " Get movie recommendations\n", - "\n", - " Args:\n", - " query (str): User query\n", - " mode (str): Retrieval mode. One of (default, text_search, hybrid)\n", - " \"\"\"\n", - " query_engine = vector_store_index.as_query_engine(\n", - " similarity_top_k=5, vector_store_query_mode=mode, **kwargs\n", - " )\n", - " response = query_engine.query(query)\n", - " nodes = response.source_nodes\n", - " for node in nodes:\n", - " title = node.metadata[\"title\"]\n", - " rating = node.metadata[\"rating\"]\n", - " score = node.score\n", - " print(f\"Title: {title} | Rating: {rating} | Relevance Score: {score}\")" - ] + "5f822791ad0243d99cffb09f57b6257d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_13eec1cf9f3b4e27995eb7735bbf43aa", + "placeholder": "​", + "style": "IPY_MODEL_8bda824cef9c493b83704d511554954c", + "value": "datasets/fiqa.zip: 100%" + } }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Full-text search" - ] + "6275b672934d4cc383cc4c18f3dfe4b7": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Title: Hellboy II: The Golden Army | Rating: 7.0 | Relevance Score: 5.93734884262085\n", - "Title: The Matrix Revolutions | Rating: 6.7 | Relevance Score: 4.574477195739746\n", - "Title: The Matrix | Rating: 8.7 | Relevance Score: 4.387373924255371\n", - "Title: Go with Peace Jamil | Rating: 6.9 | Relevance Score: 3.5394840240478516\n", - "Title: Terminator Salvation | Rating: 6.7 | Relevance Score: 3.3378987312316895\n" - ] - } - ], - "source": [ - "get_recommendations(\n", - " query=\"Action movies about humans fighting machines\",\n", - " mode=\"text_search\",\n", - ")" - ] + "6770f34c4be644cda13221e47d00ca28": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Vector search" - ] + "6a3ffc1cb8764532b215d51cae6e44be": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Title: Death Machine | Rating: 5.7 | Relevance Score: 0.7407287359237671\n", - "Title: Real Steel | Rating: 7.1 | Relevance Score: 0.7364246845245361\n", - "Title: Soldier | Rating: 5.9 | Relevance Score: 0.7282171249389648\n", - "Title: Terminator 3: Rise of the Machines | Rating: 6.4 | Relevance Score: 0.7266112565994263\n", - "Title: Last Action Hero | Rating: 6.2 | Relevance Score: 0.7250100374221802\n" - ] - } - ], - "source": [ - "get_recommendations(\n", - " query=\"Action movies about humans fighting machines\", mode=\"default\"\n", - ")" - ] + "6a61062dbe92469889f767985c4f5b59": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Hybrid search" - ] + "72b0800f217f4559aea1c0db64d6594c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e71944737601445a9e8a1f39fe32d445", + "placeholder": "​", + "style": "IPY_MODEL_edd9d4c3787f44e2a6d7fe43dec354f2", + "value": " 57638/57638 [00:00<00:00, 91199.90it/s]" + } }, - { - "cell_type": "code", - "execution_count": 54, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Title: Hellboy II: The Golden Army | Rating: 7.0 | Relevance Score: 0.5\n", - "Title: Death Machine | Rating: 5.7 | Relevance Score: 0.5\n", - "Title: The Matrix Revolutions | Rating: 6.7 | Relevance Score: 0.25\n", - "Title: Real Steel | Rating: 7.1 | Relevance Score: 0.25\n", - "Title: Soldier | Rating: 5.9 | Relevance Score: 0.16666666666666666\n" - ] - } - ], - "source": [ - "# Vector and full-text search weighted equal by default\n", - "get_recommendations(query=\"Action movies about humans fighting machines\", mode=\"hybrid\")" - ] + "7350acfbe3bd4e1cb4ff49290a6cd58f": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Title: Death Machine | Rating: 5.7 | Relevance Score: 0.7\n", - "Title: Real Steel | Rating: 7.1 | Relevance Score: 0.35\n", - "Title: Hellboy II: The Golden Army | Rating: 7.0 | Relevance Score: 0.30000000000000004\n", - "Title: Soldier | Rating: 5.9 | Relevance Score: 0.2333333333333333\n", - "Title: Terminator 3: Rise of the Machines | Rating: 6.4 | Relevance Score: 0.175\n" - ] - } + "73cddc3fa8bb4495b335018fae3b063e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_4950b546681b4c8cbec0a9c3acf08c37", + "IPY_MODEL_30ccab778b894d8c86359fb850ee76f2", + "IPY_MODEL_c25ebc49169a4fccae65c84ba71b50c7" ], - "source": [ - "# Higher alpha, vector search dominates\n", - "get_recommendations(\n", - " query=\"Action movies about humans fighting machines\",\n", - " mode=\"hybrid\",\n", - " alpha=0.7,\n", - ")" - ] + "layout": "IPY_MODEL_00135b96c1e34abf94352e5d14dfbfc2" + } }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Title: Hellboy II: The Golden Army | Rating: 7.0 | Relevance Score: 0.7\n", - "Title: The Matrix Revolutions | Rating: 6.7 | Relevance Score: 0.35\n", - "Title: Death Machine | Rating: 5.7 | Relevance Score: 0.3\n", - "Title: The Matrix | Rating: 8.7 | Relevance Score: 0.2333333333333333\n", - "Title: Go with Peace Jamil | Rating: 6.9 | Relevance Score: 0.175\n" - ] - } + "84d25add023044d68f383b81dacaf462": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_c45d82a40d2c4096b6c00b6c93290add", + "placeholder": "​", + "style": "IPY_MODEL_9cbf8f18e9dd4cd3acc274ad3f4868ae", + "value": " 2.69M/2.69M [00:00<00:00, 6.83MiB/s]" + } + }, + "879141a9900d4741985af9ee5f230760": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_5f822791ad0243d99cffb09f57b6257d", + "IPY_MODEL_f9596cf74c4b428594a0be76406d96be", + "IPY_MODEL_b014d38bd40740a18eaf90a6d2f69439" ], - "source": [ - "# Lower alpha, full-text search dominates\n", - "get_recommendations(\n", - " query=\"Action movies about humans fighting machines\",\n", - " mode=\"hybrid\",\n", - " alpha=0.3,\n", - ")" - ] + "layout": "IPY_MODEL_6a3ffc1cb8764532b215d51cae6e44be" + } }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Combining metadata filters with search" - ] + "8bda824cef9c493b83704d511554954c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } }, - { - "cell_type": "code", - "execution_count": 57, - "metadata": {}, - "outputs": [], - "source": [ - "from llama_index.core.vector_stores import (\n", - " MetadataFilter,\n", - " MetadataFilters,\n", - " FilterOperator,\n", - " FilterCondition,\n", - ")" - ] + "983b3ad86d71468c9efc7e01926c70e6": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": {}, - "outputs": [], - "source": [ - "filters = MetadataFilters(\n", - " filters=[\n", - " MetadataFilter(key=\"metadata.rating\", value=7, operator=FilterOperator.GT),\n", - " MetadataFilter(\n", - " key=\"metadata.languages\", value=\"English\", operator=FilterOperator.EQ\n", - " ),\n", - " ],\n", - " condition=FilterCondition.AND,\n", - ")" - ] + "9903eb80686c492aa8a5e3190ccc798a": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Title: Real Steel | Rating: 7.1 | Relevance Score: 0.7\n", - "Title: T2 3-D: Battle Across Time | Rating: 7.8 | Relevance Score: 0.35\n", - "Title: The Matrix | Rating: 8.7 | Relevance Score: 0.30000000000000004\n", - "Title: Predator | Rating: 7.8 | Relevance Score: 0.2333333333333333\n", - "Title: Transformers | Rating: 7.1 | Relevance Score: 0.175\n" - ] - } + "9cbf8f18e9dd4cd3acc274ad3f4868ae": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "b014d38bd40740a18eaf90a6d2f69439": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_2001c71b7c0649ad94991dc00c2c1c2b", + "placeholder": "​", + "style": "IPY_MODEL_0b639c296a6e42e883957f4053e08881", + "value": " 17.1M/17.1M [00:06<00:00, 2.10MiB/s]" + } + }, + "b446bbe72b8344dab8c5b637ff3e48bf": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "b7df766690574c09b4942e0d27151171": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b8c4d550a4fb475d8a66c1e5deefb1f2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "c25ebc49169a4fccae65c84ba71b50c7": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_7350acfbe3bd4e1cb4ff49290a6cd58f", + "placeholder": "​", + "style": "IPY_MODEL_5b4d7df8ac4e4a788d7684f47f1d1b76", + "value": " 5183/5183 [00:00<00:00, 45467.14it/s]" + } + }, + "c2c384a4406b4b9f9dfc57779d7246ee": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "c3375ea1a272481babcaece7f79b428e": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "c45d82a40d2c4096b6c00b6c93290add": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "e260dd2233ff479db1471ec42f0b907a": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "e65a397cb2e44371886c3f51362a9bc6": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "e71944737601445a9e8a1f39fe32d445": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "edd9d4c3787f44e2a6d7fe43dec354f2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "ef9546a04f6d47e081b7021376e1fdab": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_f2be4ffe3b984e9989af25faceb3c9fc", + "IPY_MODEL_4cbd2428f91c40d092e1c3bc80171123", + "IPY_MODEL_72b0800f217f4559aea1c0db64d6594c" ], - "source": [ - "get_recommendations(\n", - " query=\"Action movies about humans fighting machines\",\n", - " mode=\"hybrid\",\n", - " alpha=0.7,\n", - " filters=filters,\n", - ")" - ] - } - ], - "metadata": { - "colab": { - "provenance": [], - "toc_visible": true + "layout": "IPY_MODEL_983b3ad86d71468c9efc7e01926c70e6" + } }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" + "f22b82b8010a4a79b0b42908966cc89e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_6770f34c4be644cda13221e47d00ca28", + "placeholder": "​", + "style": "IPY_MODEL_c2c384a4406b4b9f9dfc57779d7246ee", + "value": "datasets/scifact.zip: 100%" + } }, - "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.12.1" + "f2be4ffe3b984e9989af25faceb3c9fc": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e260dd2233ff479db1471ec42f0b907a", + "placeholder": "​", + "style": "IPY_MODEL_b446bbe72b8344dab8c5b637ff3e48bf", + "value": "100%" + } }, - "widgets": { - "application/vnd.jupyter.widget-state+json": { - "00135b96c1e34abf94352e5d14dfbfc2": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "0b639c296a6e42e883957f4053e08881": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "13eec1cf9f3b4e27995eb7735bbf43aa": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "148567c981e74f1a9b840fb5463f6c1f": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "2001c71b7c0649ad94991dc00c2c1c2b": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "30ccab778b894d8c86359fb850ee76f2": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_b7df766690574c09b4942e0d27151171", - "max": 5183, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_e65a397cb2e44371886c3f51362a9bc6", - "value": 5183 - } - }, - "33ef6c005a52428cb00a9e7ccb0e6b2c": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "350c3f298a7b414c8ab6ea4492fb98c3": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "35b668058eca435a86829f32ca421859": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_33ef6c005a52428cb00a9e7ccb0e6b2c", - "max": 2816079, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_b8c4d550a4fb475d8a66c1e5deefb1f2", - "value": 2816079 - } - }, - "4950b546681b4c8cbec0a9c3acf08c37": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_350c3f298a7b414c8ab6ea4492fb98c3", - "placeholder": "​", - "style": "IPY_MODEL_6275b672934d4cc383cc4c18f3dfe4b7", - "value": "100%" - } - }, - "4cbd2428f91c40d092e1c3bc80171123": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_fbf3da22c9954c3ab5995fff682084ba", - "max": 57638, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_6a61062dbe92469889f767985c4f5b59", - "value": 57638 - } - }, - "51c3a472109243c681898fb32aeda7d7": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_f22b82b8010a4a79b0b42908966cc89e", - "IPY_MODEL_35b668058eca435a86829f32ca421859", - "IPY_MODEL_84d25add023044d68f383b81dacaf462" - ], - "layout": "IPY_MODEL_c3375ea1a272481babcaece7f79b428e" - } - }, - "5b4d7df8ac4e4a788d7684f47f1d1b76": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "5f822791ad0243d99cffb09f57b6257d": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_13eec1cf9f3b4e27995eb7735bbf43aa", - "placeholder": "​", - "style": "IPY_MODEL_8bda824cef9c493b83704d511554954c", - "value": "datasets/fiqa.zip: 100%" - } - }, - "6275b672934d4cc383cc4c18f3dfe4b7": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "6770f34c4be644cda13221e47d00ca28": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "6a3ffc1cb8764532b215d51cae6e44be": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "6a61062dbe92469889f767985c4f5b59": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "72b0800f217f4559aea1c0db64d6594c": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_e71944737601445a9e8a1f39fe32d445", - "placeholder": "​", - "style": "IPY_MODEL_edd9d4c3787f44e2a6d7fe43dec354f2", - "value": " 57638/57638 [00:00<00:00, 91199.90it/s]" - } - }, - "7350acfbe3bd4e1cb4ff49290a6cd58f": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "73cddc3fa8bb4495b335018fae3b063e": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_4950b546681b4c8cbec0a9c3acf08c37", - "IPY_MODEL_30ccab778b894d8c86359fb850ee76f2", - "IPY_MODEL_c25ebc49169a4fccae65c84ba71b50c7" - ], - "layout": "IPY_MODEL_00135b96c1e34abf94352e5d14dfbfc2" - } - }, - "84d25add023044d68f383b81dacaf462": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_c45d82a40d2c4096b6c00b6c93290add", - "placeholder": "​", - "style": "IPY_MODEL_9cbf8f18e9dd4cd3acc274ad3f4868ae", - "value": " 2.69M/2.69M [00:00<00:00, 6.83MiB/s]" - } - }, - "879141a9900d4741985af9ee5f230760": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_5f822791ad0243d99cffb09f57b6257d", - "IPY_MODEL_f9596cf74c4b428594a0be76406d96be", - "IPY_MODEL_b014d38bd40740a18eaf90a6d2f69439" - ], - "layout": "IPY_MODEL_6a3ffc1cb8764532b215d51cae6e44be" - } - }, - "8bda824cef9c493b83704d511554954c": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "983b3ad86d71468c9efc7e01926c70e6": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "9903eb80686c492aa8a5e3190ccc798a": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "9cbf8f18e9dd4cd3acc274ad3f4868ae": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "b014d38bd40740a18eaf90a6d2f69439": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_2001c71b7c0649ad94991dc00c2c1c2b", - "placeholder": "​", - "style": "IPY_MODEL_0b639c296a6e42e883957f4053e08881", - "value": " 17.1M/17.1M [00:06<00:00, 2.10MiB/s]" - } - }, - "b446bbe72b8344dab8c5b637ff3e48bf": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "b7df766690574c09b4942e0d27151171": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "b8c4d550a4fb475d8a66c1e5deefb1f2": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "c25ebc49169a4fccae65c84ba71b50c7": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_7350acfbe3bd4e1cb4ff49290a6cd58f", - "placeholder": "​", - "style": "IPY_MODEL_5b4d7df8ac4e4a788d7684f47f1d1b76", - "value": " 5183/5183 [00:00<00:00, 45467.14it/s]" - } - }, - "c2c384a4406b4b9f9dfc57779d7246ee": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "c3375ea1a272481babcaece7f79b428e": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "c45d82a40d2c4096b6c00b6c93290add": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "e260dd2233ff479db1471ec42f0b907a": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "e65a397cb2e44371886c3f51362a9bc6": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "ProgressStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "e71944737601445a9e8a1f39fe32d445": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "edd9d4c3787f44e2a6d7fe43dec354f2": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "DescriptionStyleModel", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "ef9546a04f6d47e081b7021376e1fdab": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HBoxModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_f2be4ffe3b984e9989af25faceb3c9fc", - "IPY_MODEL_4cbd2428f91c40d092e1c3bc80171123", - "IPY_MODEL_72b0800f217f4559aea1c0db64d6594c" - ], - "layout": "IPY_MODEL_983b3ad86d71468c9efc7e01926c70e6" - } - }, - "f22b82b8010a4a79b0b42908966cc89e": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_6770f34c4be644cda13221e47d00ca28", - "placeholder": "​", - "style": "IPY_MODEL_c2c384a4406b4b9f9dfc57779d7246ee", - "value": "datasets/scifact.zip: 100%" - } - }, - "f2be4ffe3b984e9989af25faceb3c9fc": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "HTMLModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_e260dd2233ff479db1471ec42f0b907a", - "placeholder": "​", - "style": "IPY_MODEL_b446bbe72b8344dab8c5b637ff3e48bf", - "value": "100%" - } - }, - "f9596cf74c4b428594a0be76406d96be": { - "model_module": "@jupyter-widgets/controls", - "model_module_version": "1.5.0", - "model_name": "FloatProgressModel", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "success", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_9903eb80686c492aa8a5e3190ccc798a", - "max": 17948027, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_148567c981e74f1a9b840fb5463f6c1f", - "value": 17948027 - } - }, - "fbf3da22c9954c3ab5995fff682084ba": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "1.2.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - } - } + "f9596cf74c4b428594a0be76406d96be": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_9903eb80686c492aa8a5e3190ccc798a", + "max": 17948027, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_148567c981e74f1a9b840fb5463f6c1f", + "value": 17948027 + } + }, + "fbf3da22c9954c3ab5995fff682084ba": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } } - }, - "nbformat": 4, - "nbformat_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 } diff --git a/notebooks/techniques/retrieval_strategies_mongodb_llamaindex_togetherai.ipynb b/notebooks/techniques/retrieval_strategies_mongodb_llamaindex_togetherai.ipynb index 6fc6d04..7c24f6b 100644 --- a/notebooks/techniques/retrieval_strategies_mongodb_llamaindex_togetherai.ipynb +++ b/notebooks/techniques/retrieval_strategies_mongodb_llamaindex_togetherai.ipynb @@ -90,8 +90,9 @@ }, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "import os\n", + "\n", "from pymongo import MongoClient" ] }, @@ -137,8 +138,8 @@ }, "outputs": [], "source": [ - "from datasets import load_dataset\n", "import pandas as pd\n", + "from datasets import load_dataset\n", "from llama_index.core import Document" ] }, @@ -231,13 +232,13 @@ }, "outputs": [], "source": [ + "from llama_index.core import StorageContext, VectorStoreIndex\n", + "from llama_index.core.settings import Settings\n", "from llama_index.embeddings.together import TogetherEmbedding\n", "from llama_index.llms.together import TogetherLLM\n", "from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch\n", - "from llama_index.core.settings import Settings\n", - "from llama_index.core import ServiceContext, VectorStoreIndex, StorageContext\n", - "from pymongo.operations import SearchIndexModel\n", - "from pymongo.errors import OperationFailure" + "from pymongo.errors import OperationFailure\n", + "from pymongo.operations import SearchIndexModel" ] }, { @@ -604,10 +605,10 @@ "outputs": [], "source": [ "from llama_index.core.vector_stores import (\n", + " FilterCondition,\n", + " FilterOperator,\n", " MetadataFilter,\n", " MetadataFilters,\n", - " FilterOperator,\n", - " FilterCondition,\n", ")" ] }, diff --git a/notebooks/workshops/Pragmatic_LLM_Application_Introduction_From_RAG_to_Agents_with_MongoDB.ipynb b/notebooks/workshops/Pragmatic_LLM_Application_Introduction_From_RAG_to_Agents_with_MongoDB.ipynb index 059f235..03dc8a8 100644 --- a/notebooks/workshops/Pragmatic_LLM_Application_Introduction_From_RAG_to_Agents_with_MongoDB.ipynb +++ b/notebooks/workshops/Pragmatic_LLM_Application_Introduction_From_RAG_to_Agents_with_MongoDB.ipynb @@ -181,9 +181,9 @@ }, "outputs": [], "source": [ - "import pandas as pd\n", "import random\n", - "import json" + "\n", + "import pandas as pd" ] }, { @@ -1439,9 +1439,9 @@ }, "outputs": [], "source": [ - "os.environ[\"MONGO_URI\"] = \"\"\n", + "MONGO_URI = os.environ.get(\"MONGO_URI\")\n", "\n", - "OPENAI_API_KEY = os.environ.get(\"MONGO_URI\")" + "OPENAI_API_KEY = os.environ.get(\"OPENAI_API_KEY\")" ] }, { @@ -2196,8 +2196,8 @@ }, "outputs": [], "source": [ - "from langchain_openai import OpenAIEmbeddings, ChatOpenAI\n", "from langchain_mongodb import MongoDBAtlasVectorSearch\n", + "from langchain_openai import ChatOpenAI, OpenAIEmbeddings\n", "\n", "embedding_model = OpenAIEmbeddings(\n", " model=OPEN_AI_EMBEDDING_MODEL, dimensions=OPEN_AI_EMBEDDING_MODEL_DIMENSION\n", diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..5d23400 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,32 @@ +target-version = "py38" + +exclude = [".evergreen/csfle/bottle.py"] + +[lint] +extend-select = [ + "B", # flake8-bugbear + "EXE", # flake8-executable + "F", # pyflakes + "FURB", # refurb + "I", # isort + "ICN", # flake8-import-conventions + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "RUF", # Ruff-specific + "UP", # pyupgrade + "YTT", # flake8-2020 +] +ignore = [ + "F811", # Redefinition of unused, + "B007", # Loop control variable `index` not used within loop body + "B904", # Within an `except` clause, raise exceptions with `raise ... from err`" + "RUF005", # Consider iterable unpacking instead of concatenation" + "RUF015", # Prefer `next(iter(queries.items()))` over single element slice + "F841", # Local variable `full_text_search_result` is assigned to but never used" +] +unfixable = ["F401"] + +[lint.per-file-ignores] +".evergreen/ocsp/mock_ocsp_responder.py" = ["PLW"] +".evergreen/csfle/kms_*.py" = ["PLW"] +".evergreen/csfle/gcpkms/mock_server.py" = ["PLW"] diff --git a/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb b/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb index 9b86de5..10a0489 100644 --- a/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb +++ b/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb @@ -106,8 +106,8 @@ }, "outputs": [], "source": [ - "import os\n", "import getpass\n", + "import os\n", "\n", "\n", "# Function to securely get and set environment variables\n", @@ -646,9 +646,10 @@ }, "outputs": [], "source": [ - "import voyageai\n", "from typing import Optional\n", "\n", + "import voyageai\n", + "\n", "# Initialize the voyageai client\n", "vo = voyageai.Client()\n", "\n", @@ -1271,8 +1272,7 @@ " # Connection successful\n", " print(\"Connection to MongoDB successful\")\n", " return client\n", - " else:\n", - " print(\"Connection to MongoDB failed\")\n", + " print(\"Connection to MongoDB failed\")\n", " return None\n", "\n", "\n", @@ -1406,6 +1406,7 @@ "outputs": [], "source": [ "import time\n", + "\n", "from pymongo.operations import SearchIndexModel\n", "\n", "\n", @@ -1435,7 +1436,7 @@ " return result\n", "\n", " except Exception as e:\n", - " print(f\"Error creating new vector search index '{index_name}': {str(e)}\")\n", + " print(f\"Error creating new vector search index '{index_name}': {e!s}\")\n", " return None" ] }, @@ -1531,7 +1532,7 @@ "def vector_search(\n", " user_query,\n", " collection,\n", - " additional_stages=[],\n", + " additional_stages=None,\n", " vector_search_index_name=\"vector_index\",\n", "):\n", " \"\"\"\n", @@ -1592,6 +1593,7 @@ " }\n", "\n", " # Define the aggregate pipeline with the vector search stage and additional stages\n", + " additional_stages = additional_stages or []\n", " pipeline = [vector_search_stage, unset_stage, project_stage] + additional_stages\n", "\n", " # Execute the search\n", @@ -2169,7 +2171,6 @@ } ], "source": [ - "import pprint\n", "\n", "print(response)" ] @@ -2285,12 +2286,11 @@ "source": [ "import pickle\n", "from contextlib import AbstractContextManager\n", + "from datetime import datetime, timezone\n", "from types import TracebackType\n", - "from typing import Any, Dict, Optional, AsyncIterator, Union, List, Tuple\n", + "from typing import Any, AsyncIterator, Dict, List, Optional, Tuple, Union\n", "\n", "from langchain_core.runnables import RunnableConfig\n", - "from typing_extensions import Self\n", - "\n", "from langgraph.checkpoint.base import (\n", " BaseCheckpointSaver,\n", " Checkpoint,\n", @@ -2300,7 +2300,7 @@ ")\n", "from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer\n", "from motor.motor_asyncio import AsyncIOMotorClient\n", - "from datetime import datetime, timezone\n", + "from typing_extensions import Self\n", "\n", "\n", "class JsonPlusSerializerCompat(JsonPlusSerializer):\n", @@ -2559,7 +2559,7 @@ " print(f\"Search index '{index_name}' created successfully\")\n", " return result\n", " except Exception as e:\n", - " print(f\"Error creating search index: {str(e)}\")\n", + " print(f\"Error creating search index: {e!s}\")\n", " return None\n", "\n", "\n", @@ -2649,11 +2649,12 @@ }, "outputs": [], "source": [ - "from typing import Dict, Any\n", + "from typing import Any, Dict\n", + "\n", "from langchain.agents import tool\n", - "from langchain_voyageai import VoyageAIEmbeddings\n", "from langchain_mongodb import MongoDBAtlasVectorSearch\n", "from langchain_mongodb.retrievers import MongoDBAtlasHybridSearchRetriever\n", + "from langchain_voyageai import VoyageAIEmbeddings\n", "\n", "embedding_model = VoyageAIEmbeddings(\n", " voyage_api_key=os.environ[\"VOYAGE_API_KEY\"], model=VOYAGEAI_EMBEDDING_MODEL\n", @@ -2794,8 +2795,7 @@ " return (\n", " f\"Successfully updated status of shipment {shipment_id} to {new_status}\"\n", " )\n", - " else:\n", - " return f\"No shipment found with ID {shipment_id}\"\n", + " return f\"No shipment found with ID {shipment_id}\"\n", " except ValueError:\n", " return \"Invalid input format. Please use 'shipment_id,new_status'\"" ] @@ -2862,7 +2862,7 @@ " # Return the results\n", " return str(list(contracts))\n", " except Exception as e:\n", - " print(f\"An error occurred: {str(e)}\")\n", + " print(f\"An error occurred: {e!s}\")\n", " return []\n", "\n", "\n", @@ -2897,7 +2897,7 @@ " # Return the results\n", " return str(list(contracts))\n", " except Exception as e:\n", - " print(f\"An error occurred: {str(e)}\")\n", + " print(f\"An error occurred: {e!s}\")\n", " return []" ] }, @@ -2993,7 +2993,6 @@ }, "outputs": [], "source": [ - "from pymongo import MongoClient\n", "from tavily import TavilyHybridClient\n", "\n", "hybrid_rag = TavilyHybridClient(\n", @@ -3048,7 +3047,7 @@ " return results\n", "\n", " except Exception as e:\n", - " print(f\"An error occurred: {str(e)}\")\n", + " print(f\"An error occurred: {e!s}\")\n", " return []" ] }, @@ -3135,7 +3134,6 @@ "outputs": [], "source": [ "from langchain_anthropic import ChatAnthropic\n", - "from langchain_openai import ChatOpenAI\n", "\n", "# Do note that Anthropic LLM has a rate/token limit\n", "# and this can affect the agentic execution\n", @@ -3162,9 +3160,10 @@ }, "outputs": [], "source": [ - "from typing import Annotated, TypedDict, List\n", - "from langchain_core.messages import BaseMessage\n", "import operator\n", + "from typing import Annotated, List, TypedDict\n", + "\n", + "from langchain_core.messages import BaseMessage\n", "\n", "\n", "class AgentState(TypedDict):\n", @@ -3189,10 +3188,9 @@ }, "outputs": [], "source": [ - "from datetime import datetime\n", - "from langchain_core.runnables import RunnableConfig\n", "from langchain_core.messages import AIMessage, ToolMessage\n", "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", + "from langchain_core.runnables import RunnableConfig\n", "\n", "system_message = \"\"\"\n", "You are an AI-powered Logistics Assistant designed to streamline operations and enhance customer service for an international shipping company. You are equipped with tools to access and process contract details, shipment information, inventory data, and supply chain updates.\n", @@ -3270,7 +3268,6 @@ }, "outputs": [], "source": [ - "from langchain_core.messages import trim_messages\n", "\n", "\n", "def agent_node(state: AgentState, config: RunnableConfig):\n", @@ -3308,9 +3305,7 @@ "outputs": [], "source": [ "import json\n", - "from typing import List, Callable\n", - "from langgraph.prebuilt import ToolNode\n", - "from langchain_core.messages import ToolMessage\n", + "from typing import List\n", "\n", "tools_by_name = {tool.name: tool for tool in toolbox}\n", "\n", @@ -3358,8 +3353,8 @@ }, "outputs": [], "source": [ - "from langgraph.graph import END, StateGraph\n", "from langchain_core.messages import BaseMessage\n", + "from langgraph.graph import END, StateGraph\n", "\n", "\n", "# Define the conditional edge that determines whether to continue or not\n", @@ -3370,8 +3365,7 @@ " if not last_message.tool_calls:\n", " return \"end\"\n", " # Otherwise if there is, we continue\n", - " else:\n", - " return \"continue\"" + " return \"continue\"" ] }, { @@ -3489,8 +3483,8 @@ "outputs": [], "source": [ "import asyncio\n", - "from langchain_core.messages import HumanMessage, AIMessage\n", - "import time\n", + "\n", + "from langchain_core.messages import HumanMessage\n", "\n", "\n", "async def chat_loop():\n", @@ -3514,7 +3508,7 @@ " for attempt in range(max_retries):\n", " try:\n", " async for chunk in graph.astream(state, config, stream_mode=\"values\"):\n", - " if \"messages\" in chunk and chunk[\"messages\"]:\n", + " if chunk.get(\"messages\"):\n", " last_message = chunk[\"messages\"][-1]\n", " if isinstance(last_message, AIMessage):\n", " last_message.name = last_message.name or \"AI\" or \"AI\"\n", @@ -3527,12 +3521,12 @@ " break\n", " except Exception as e:\n", " if attempt < max_retries - 1:\n", - " print(f\"\\nAn unexpected error occurred: {str(e)}\")\n", + " print(f\"\\nAn unexpected error occurred: {e!s}\")\n", " print(f\"\\nRetrying in {retry_delay} seconds...\")\n", " await asyncio.sleep(retry_delay)\n", " retry_delay *= 2\n", " else:\n", - " print(f\"\\nMax retries reached. API error: {str(e)}\")\n", + " print(f\"\\nMax retries reached. API error: {e!s}\")\n", " break\n", "\n", " print(\"\\n\") # New line after the complete response" diff --git a/tools/embeddings_generator/create_embeddings.py b/tools/embeddings_generator/create_embeddings.py index dbb3a5f..4bef805 100644 --- a/tools/embeddings_generator/create_embeddings.py +++ b/tools/embeddings_generator/create_embeddings.py @@ -1,9 +1,13 @@ import argparse import logging from datetime import datetime -from tqdm import tqdm +from typing import List, Union -from utils import * +import cohere +import openai +import pandas as pd +import utils +from tqdm import tqdm logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s") @@ -68,7 +72,7 @@ def get_embeddings( emb_fn = func_map.get("cohere") else: emb_fn = func_map.get("huggingface") - model = SentenceTransformer("thenlper/gte-small") + model = utils.SentenceTransformer("thenlper/gte-small") embeddings = [] for i in tqdm(range(0, len(texts), 128)): @@ -98,21 +102,21 @@ def get_data(path: str, field: str) -> pd.DataFrame: return data except Exception as e: logging.error("Error reading the CSV file.") - raise DataError(e) + raise utils.DataError(e) # Mapping provider names to their respective embedding functions func_map = { - "openai": get_openai_embeddings, - "cohere": get_cohere_embeddings, - "huggingface": get_hf_embeddings, + "openai": utils.get_openai_embeddings, + "cohere": utils.get_cohere_embeddings, + "huggingface": utils.get_hf_embeddings, } def main(): """Main function""" provider = args.type - client = get_client(provider) + client = utils.get_client(provider) path = args.path field = args.field @@ -125,8 +129,8 @@ def main(): data["embeddings"] = get_embeddings(provider, client, texts) logging.info("Ingesting data into MongoDB...") - mongo_client = get_mongo_client(args.uri) - ingest_data(mongo_client, data, args.db, args.coll) + mongo_client = utils.get_mongo_client(args.uri) + utils.ingest_data(mongo_client, data, args.db, args.coll) logging.info(f"Inserted {len(data)} documents into MongoDB.") diff --git a/tools/embeddings_generator/utils.py b/tools/embeddings_generator/utils.py index 1e9f687..9065994 100644 --- a/tools/embeddings_generator/utils.py +++ b/tools/embeddings_generator/utils.py @@ -33,7 +33,7 @@ def get_openai_client() -> openai.OpenAI: try: client.models.list() return client - except openai.AuthenticationError as e: + except openai.AuthenticationError: logging.error("OpenAI authentication failed.") raise ClientError("OpenAI authentication failed. Please check your API key.") diff --git a/tools/function_calling_mongodb_as_a_toolbox.ipynb b/tools/function_calling_mongodb_as_a_toolbox.ipynb index b79c336..ca80893 100644 --- a/tools/function_calling_mongodb_as_a_toolbox.ipynb +++ b/tools/function_calling_mongodb_as_a_toolbox.ipynb @@ -62,9 +62,9 @@ } ], "source": [ - "import os\n", - "import json\n", "import getpass\n", + "import json\n", + "import os\n", "\n", "OPENAI_API_KEY = getpass.getpass(\"OpenAI API Key: \")\n", "os.environ[\"OPENAI_API_KEY\"] = OPENAI_API_KEY\n", @@ -163,7 +163,7 @@ " json_type = \"string\" # Default to string\n", " if param_type in (int, float):\n", " json_type = \"number\"\n", - " elif param_type == bool:\n", + " elif param_type is bool:\n", " json_type = \"boolean\"\n", "\n", " tool_def[\"parameters\"][\"properties\"][param_name] = {\n", @@ -499,7 +499,6 @@ } ], "source": [ - "import json\n", "\n", "# Step 2: determine if the response from the model includes a tool call.\n", "tool_calls = response_message.tool_calls\n", From 16add1cb19be1328836247435cd9e1b928618a59 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 11 Dec 2024 15:02:56 -0500 Subject: [PATCH 2/5] bump to 3.9+ --- ...ry_safety_assistant_with_langgraph_langchain_mongodb.ipynb | 3 ++- ..._analyst_assistant_agentic_chatbot_langgraph_mongodb.ipynb | 3 ++- .../agents/hr_agentic_chatbot_with_langgraph_claude.ipynb | 3 ++- ruff.toml | 4 +++- ...d_Supply_Chain_Management_for_International_Shipping.ipynb | 3 ++- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/notebooks/agents/agentic_rag_factory_safety_assistant_with_langgraph_langchain_mongodb.ipynb b/notebooks/agents/agentic_rag_factory_safety_assistant_with_langgraph_langchain_mongodb.ipynb index 5ef9c7b..33207cd 100644 --- a/notebooks/agents/agentic_rag_factory_safety_assistant_with_langgraph_langchain_mongodb.ipynb +++ b/notebooks/agents/agentic_rag_factory_safety_assistant_with_langgraph_langchain_mongodb.ipynb @@ -2798,10 +2798,11 @@ "outputs": [], "source": [ "import pickle\n", + "from collections.abc import AsyncIterator\n", "from contextlib import AbstractContextManager\n", "from datetime import datetime, timezone\n", "from types import TracebackType\n", - "from typing import Any, AsyncIterator, Dict, List, Optional, Tuple, Union\n", + "from typing import Any, Dict, List, Optional, Tuple, Union\n", "\n", "from langchain_core.runnables import RunnableConfig\n", "from langgraph.checkpoint.base import (\n", diff --git a/notebooks/agents/asset_management_analyst_assistant_agentic_chatbot_langgraph_mongodb.ipynb b/notebooks/agents/asset_management_analyst_assistant_agentic_chatbot_langgraph_mongodb.ipynb index 3e515b2..2d0b1f5 100644 --- a/notebooks/agents/asset_management_analyst_assistant_agentic_chatbot_langgraph_mongodb.ipynb +++ b/notebooks/agents/asset_management_analyst_assistant_agentic_chatbot_langgraph_mongodb.ipynb @@ -1971,10 +1971,11 @@ "outputs": [], "source": [ "import pickle\n", + "from collections.abc import AsyncIterator\n", "from contextlib import AbstractContextManager\n", "from datetime import datetime, timezone\n", "from types import TracebackType\n", - "from typing import Any, AsyncIterator, Dict, List, Optional, Tuple, Union\n", + "from typing import Any, Dict, List, Optional, Tuple, Union\n", "\n", "from langchain_core.runnables import RunnableConfig\n", "from langgraph.checkpoint.base import (\n", diff --git a/notebooks/agents/hr_agentic_chatbot_with_langgraph_claude.ipynb b/notebooks/agents/hr_agentic_chatbot_with_langgraph_claude.ipynb index 354b4ac..786ee10 100644 --- a/notebooks/agents/hr_agentic_chatbot_with_langgraph_claude.ipynb +++ b/notebooks/agents/hr_agentic_chatbot_with_langgraph_claude.ipynb @@ -1798,7 +1798,8 @@ "outputs": [], "source": [ "import operator\n", - "from typing import Annotated, Sequence, TypedDict\n", + "from collections.abc import Sequence\n", + "from typing import Annotated, TypedDict\n", "\n", "from langchain_core.messages import BaseMessage\n", "\n", diff --git a/ruff.toml b/ruff.toml index 5d23400..fcf4752 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,4 +1,4 @@ -target-version = "py38" +target-version = "py39" exclude = [".evergreen/csfle/bottle.py"] @@ -23,6 +23,8 @@ ignore = [ "RUF005", # Consider iterable unpacking instead of concatenation" "RUF015", # Prefer `next(iter(queries.items()))` over single element slice "F841", # Local variable `full_text_search_result` is assigned to but never used" + "UP006", # Use `list` instead of `List` for type annotation" + "UP035", # `typing.List` is deprecated, use `list` instead" ] unfixable = ["F401"] diff --git a/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb b/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb index 10a0489..31242fc 100644 --- a/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb +++ b/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb @@ -2285,10 +2285,11 @@ "outputs": [], "source": [ "import pickle\n", + "from collections.abc import AsyncIterator\n", "from contextlib import AbstractContextManager\n", "from datetime import datetime, timezone\n", "from types import TracebackType\n", - "from typing import Any, AsyncIterator, Dict, List, Optional, Tuple, Union\n", + "from typing import Any, Dict, List, Optional, Tuple, Union\n", "\n", "from langchain_core.runnables import RunnableConfig\n", "from langgraph.checkpoint.base import (\n", From 0b72c0654c0c9c842d30821909bcd807abb47cf6 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 11 Dec 2024 15:04:04 -0500 Subject: [PATCH 3/5] lint --- .../rag_chatbot_with_cohere_and_mongodb.ipynb | 1 - ...ed_vectors_using_cohere_mongodb_beir.ipynb | 1 - ...trival_techniques_mongondb_langchain.ipynb | 579 ++++++++++-------- ...or_ingestion_with_cohere_and_mongodb.ipynb | 1 - ...anagement_for_International_Shipping.ipynb | 3 - ...unction_calling_mongodb_as_a_toolbox.ipynb | 1 - 6 files changed, 329 insertions(+), 257 deletions(-) diff --git a/notebooks/rag/rag_chatbot_with_cohere_and_mongodb.ipynb b/notebooks/rag/rag_chatbot_with_cohere_and_mongodb.ipynb index 03d6dbf..d5a31be 100644 --- a/notebooks/rag/rag_chatbot_with_cohere_and_mongodb.ipynb +++ b/notebooks/rag/rag_chatbot_with_cohere_and_mongodb.ipynb @@ -1983,7 +1983,6 @@ } ], "source": [ - "\n", "query = \"What companies have negative market reports or negative sentiment that might deter from investment in the long term\"\n", "\n", "get_knowledge = vector_search(query, collection)\n", diff --git a/notebooks/techniques/advanced_evaluation_of_quantized_vectors_using_cohere_mongodb_beir.ipynb b/notebooks/techniques/advanced_evaluation_of_quantized_vectors_using_cohere_mongodb_beir.ipynb index a77d65d..38b48c9 100644 --- a/notebooks/techniques/advanced_evaluation_of_quantized_vectors_using_cohere_mongodb_beir.ipynb +++ b/notebooks/techniques/advanced_evaluation_of_quantized_vectors_using_cohere_mongodb_beir.ipynb @@ -617,7 +617,6 @@ }, "outputs": [], "source": [ - "\n", "# Initialize Cohere Client\n", "co = cohere.Client(COHERE_API_KEY)" ] diff --git a/notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb b/notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb index 000f348..6387c58 100644 --- a/notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb +++ b/notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb @@ -99,7 +99,7 @@ "outputs": [], "source": [ "metric_names = [\"NDCG\", \"MAP\", \"Recall\", \"Precision\"]\n", - "information_retrieval_search_methods = ['Lexical', 'Vector', 'Hybrid']" + "information_retrieval_search_methods = [\"Lexical\", \"Vector\", \"Hybrid\"]" ] }, { @@ -323,21 +323,24 @@ "\n", "\n", "def get_mongo_client(mongo_uri):\n", - " \"\"\"Establish and validate connection to the MongoDB.\"\"\"\n", + " \"\"\"Establish and validate connection to the MongoDB.\"\"\"\n", "\n", - " client = pymongo.MongoClient(mongo_uri, appname=\"devrel.showcase.information_retrieval_eval.python\")\n", + " client = pymongo.MongoClient(\n", + " mongo_uri, appname=\"devrel.showcase.information_retrieval_eval.python\"\n", + " )\n", + "\n", + " # Validate the connection\n", + " ping_result = client.admin.command(\"ping\")\n", + " if ping_result.get(\"ok\") == 1.0:\n", + " # Connection successful\n", + " print(\"Connection to MongoDB successful\")\n", + " return client\n", + " print(\"Connection to MongoDB failed\")\n", + " return None\n", "\n", - " # Validate the connection\n", - " ping_result = client.admin.command('ping')\n", - " if ping_result.get('ok') == 1.0:\n", - " # Connection successful\n", - " print(\"Connection to MongoDB successful\")\n", - " return client\n", - " print(\"Connection to MongoDB failed\")\n", - " return None\n", "\n", "if not MONGO_URI:\n", - " print(\"MONGO_URI not set in environment variables\")" + " print(\"MONGO_URI not set in environment variables\")" ] }, { @@ -349,26 +352,36 @@ "outputs": [], "source": [ "def ingest_data(db, corpus=None, corpus_collection_name=\"\", queries=None, qrels=None):\n", - " \"\"\"Ingest data into MongoDB collections.\"\"\"\n", - " # Ingest corpus\n", - " if corpus and corpus_collection_name:\n", - " corpus_docs = [{\"_id\": doc_id, \"text\": doc[\"text\"], \"title\": doc[\"title\"]} for doc_id, doc in corpus.items()]\n", - " db[corpus_collection_name].insert_many(corpus_docs)\n", - " print(f\"Ingested {len(corpus_docs)} documents into {corpus_collection_name}\")\n", - "\n", - " # Ingest queries\n", - " if queries:\n", - " query_docs = [{\"_id\": query_id, \"text\": query_text} for query_id, query_text in queries.items()]\n", - " db[QUERIES_COLLECTION_NAME].insert_many(query_docs)\n", - " print(f\"Ingested {len(query_docs)} queries into {QUERIES_COLLECTION_NAME}\")\n", - "\n", - " # Ingest qrels\n", - " if qrels:\n", - " qrel_docs = [{\"query_id\": query_id, \"doc_id\": doc_id, \"relevance\": relevance}\n", - " for query_id, relevance_dict in qrels.items()\n", - " for doc_id, relevance in relevance_dict.items()]\n", - " db[QRELS_COLLECTION_NAME].insert_many(qrel_docs)\n", - " print(f\"Ingested {len(qrel_docs)} relevance judgments into {QRELS_COLLECTION_NAME}\")" + " \"\"\"Ingest data into MongoDB collections.\"\"\"\n", + " # Ingest corpus\n", + " if corpus and corpus_collection_name:\n", + " corpus_docs = [\n", + " {\"_id\": doc_id, \"text\": doc[\"text\"], \"title\": doc[\"title\"]}\n", + " for doc_id, doc in corpus.items()\n", + " ]\n", + " db[corpus_collection_name].insert_many(corpus_docs)\n", + " print(f\"Ingested {len(corpus_docs)} documents into {corpus_collection_name}\")\n", + "\n", + " # Ingest queries\n", + " if queries:\n", + " query_docs = [\n", + " {\"_id\": query_id, \"text\": query_text}\n", + " for query_id, query_text in queries.items()\n", + " ]\n", + " db[QUERIES_COLLECTION_NAME].insert_many(query_docs)\n", + " print(f\"Ingested {len(query_docs)} queries into {QUERIES_COLLECTION_NAME}\")\n", + "\n", + " # Ingest qrels\n", + " if qrels:\n", + " qrel_docs = [\n", + " {\"query_id\": query_id, \"doc_id\": doc_id, \"relevance\": relevance}\n", + " for query_id, relevance_dict in qrels.items()\n", + " for doc_id, relevance in relevance_dict.items()\n", + " ]\n", + " db[QRELS_COLLECTION_NAME].insert_many(qrel_docs)\n", + " print(\n", + " f\"Ingested {len(qrel_docs)} relevance judgments into {QRELS_COLLECTION_NAME}\"\n", + " )" ] }, { @@ -383,67 +396,68 @@ "from pymongo.operations import SearchIndexModel\n", "\n", "\n", - "def setup_vector_search_index_with_filter(collection, index_definition, index_name=\"vector_index\"):\n", - " \"\"\"\n", - " Setup a vector search index for a MongoDB collection.\n", + "def setup_vector_search_index_with_filter(\n", + " collection, index_definition, index_name=\"vector_index\"\n", + "):\n", + " \"\"\"\n", + " Setup a vector search index for a MongoDB collection.\n", "\n", - " Args:\n", - " collection: MongoDB collection object\n", - " index_definition: Dictionary containing the index definition\n", - " index_name: Name of the index (default: \"vector_index_with_filter\")\n", - " \"\"\"\n", - " new_vector_search_index_model = SearchIndexModel(\n", - " definition=index_definition,\n", - " name=index_name,\n", - " )\n", + " Args:\n", + " collection: MongoDB collection object\n", + " index_definition: Dictionary containing the index definition\n", + " index_name: Name of the index (default: \"vector_index_with_filter\")\n", + " \"\"\"\n", + " new_vector_search_index_model = SearchIndexModel(\n", + " definition=index_definition,\n", + " name=index_name,\n", + " )\n", "\n", - " # Create the new index\n", - " try:\n", - " result = collection.create_search_index(model=new_vector_search_index_model)\n", - " print(f\"Creating index '{index_name}'...\")\n", - " # time.sleep(20) # Sleep for 20 seconds\n", - " print(f\"New index '{index_name}' created successfully:\", result)\n", - " except Exception as e:\n", - " print(f\"Error creating new vector search index '{index_name}': {e!s}\")\n", + " # Create the new index\n", + " try:\n", + " result = collection.create_search_index(model=new_vector_search_index_model)\n", + " print(f\"Creating index '{index_name}'...\")\n", + " # time.sleep(20) # Sleep for 20 seconds\n", + " print(f\"New index '{index_name}' created successfully:\", result)\n", + " except Exception as e:\n", + " print(f\"Error creating new vector search index '{index_name}': {e!s}\")\n", "\n", "\n", "def create_collection_search_index(collection, index_definition, index_name):\n", - " \"\"\"\n", - " Create a search index for a MongoDB Atlas collection.\n", + " \"\"\"\n", + " Create a search index for a MongoDB Atlas collection.\n", "\n", - " Args:\n", - " collection: MongoDB collection object\n", - " index_definition: Dictionary defining the index mappings\n", - " index_name: String name for the index\n", + " Args:\n", + " collection: MongoDB collection object\n", + " index_definition: Dictionary defining the index mappings\n", + " index_name: String name for the index\n", "\n", - " Returns:\n", - " str: Result of the index creation operation\n", - " \"\"\"\n", + " Returns:\n", + " str: Result of the index creation operation\n", + " \"\"\"\n", "\n", - " try:\n", - " search_index_model = SearchIndexModel(\n", - " definition=index_definition,\n", - " name=index_name\n", - " )\n", + " try:\n", + " search_index_model = SearchIndexModel(\n", + " definition=index_definition, name=index_name\n", + " )\n", "\n", - " result = collection.create_search_index(model=search_index_model)\n", - " print(f\"Search index '{index_name}' created successfully\")\n", - " return result\n", - " except Exception as e:\n", - " print(f\"Error creating search index: {e!s}\")\n", - " return None\n", + " result = collection.create_search_index(model=search_index_model)\n", + " print(f\"Search index '{index_name}' created successfully\")\n", + " return result\n", + " except Exception as e:\n", + " print(f\"Error creating search index: {e!s}\")\n", + " return None\n", "\n", "\n", "def print_collection_search_indexes(collection):\n", - " \"\"\"\n", - " Print all search indexes for a given collection.\n", + " \"\"\"\n", + " Print all search indexes for a given collection.\n", "\n", - " Args:\n", - " collection: MongoDB collection object\n", - " \"\"\"\n", - " print(f\"\\nSearch indexes for collection '{collection.name}':\")\n", - " for index in collection.list_search_indexes():\n", - " print(f\"Index: {index['name']}\")" + " Args:\n", + " collection: MongoDB collection object\n", + " \"\"\"\n", + " print(f\"\\nSearch indexes for collection '{collection.name}':\")\n", + " for index in collection.list_search_indexes():\n", + " print(f\"Index: {index['name']}\")" ] }, { @@ -455,17 +469,10 @@ "outputs": [], "source": [ "corpus_text_index_definition = {\n", - " \"mappings\": {\n", - " \"dynamic\": True,\n", - " \"fields\": {\n", - " \"text\": {\n", - " \"type\": \"string\"\n", - " },\n", - " \"title\":{\n", - " \"type\": \"string\"\n", - " }\n", + " \"mappings\": {\n", + " \"dynamic\": True,\n", + " \"fields\": {\"text\": {\"type\": \"string\"}, \"title\": {\"type\": \"string\"}},\n", " }\n", - " }\n", "}" ] }, @@ -486,7 +493,7 @@ " \"similarity\": \"cosine\",\n", " \"type\": \"knnVector\",\n", " },\n", - " }\n", + " },\n", " }\n", "}" ] @@ -514,7 +521,7 @@ "mongo_client = get_mongo_client(MONGO_URI)\n", "\n", "if mongo_client:\n", - " db = mongo_client[DB_NAME]" + " db = mongo_client[DB_NAME]" ] }, { @@ -545,8 +552,12 @@ ], "source": [ "# Clear existing collections\n", - "for collection in [CORPUS_COLLECTION_NAME, QUERIES_COLLECTION_NAME, QRELS_COLLECTION_NAME]:\n", - " db[collection].delete_many({})" + "for collection in [\n", + " CORPUS_COLLECTION_NAME,\n", + " QUERIES_COLLECTION_NAME,\n", + " QRELS_COLLECTION_NAME,\n", + "]:\n", + " db[collection].delete_many({})" ] }, { @@ -570,7 +581,9 @@ "outputs": [], "source": [ "# Create Search Index for corpus collection\n", - "create_collection_search_index(db[CORPUS_COLLECTION_NAME], corpus_text_index_definition, TEXT_SEARCH_INDEX)" + "create_collection_search_index(\n", + " db[CORPUS_COLLECTION_NAME], corpus_text_index_definition, TEXT_SEARCH_INDEX\n", + ")" ] }, { @@ -595,7 +608,9 @@ ], "source": [ "# Create Vector Search Index for corpus collection\n", - "setup_vector_search_index_with_filter(db[CORPUS_COLLECTION_NAME], corpus_vector_search_index_definition)" + "setup_vector_search_index_with_filter(\n", + " db[CORPUS_COLLECTION_NAME], corpus_vector_search_index_definition\n", + ")" ] }, { @@ -640,10 +655,13 @@ " all_doc_ids = set(corpus.keys())\n", "\n", " # Query for documents that have embeddings in a single operation\n", - " docs_with_embeddings = set(doc['_id'] for doc in collection.find(\n", - " {\"_id\": {\"$in\": list(all_doc_ids)}, \"embedding\": {\"$exists\": True}},\n", - " projection={\"_id\": 1}\n", - " ))\n", + " docs_with_embeddings = set(\n", + " doc[\"_id\"]\n", + " for doc in collection.find(\n", + " {\"_id\": {\"$in\": list(all_doc_ids)}, \"embedding\": {\"$exists\": True}},\n", + " projection={\"_id\": 1},\n", + " )\n", + " )\n", "\n", " # Find documents that need embeddings\n", " documents_to_embed = []\n", @@ -651,34 +669,40 @@ " if doc_id not in docs_with_embeddings:\n", " documents_to_embed.append((doc_id, corpus[doc_id]))\n", "\n", - " print(f\"Found {len(documents_to_embed)} documents without embeddings out of {len(corpus)} total documents.\")\n", + " print(\n", + " f\"Found {len(documents_to_embed)} documents without embeddings out of {len(corpus)} total documents.\"\n", + " )\n", "\n", " if documents_to_embed:\n", " print(\"Generating embeddings for documents without them...\")\n", " for doc_id, doc in tqdm(documents_to_embed, desc=\"Embedding documents\"):\n", " content = f\"{doc.get('title', '')} {doc.get('text', '')}\"\n", " try:\n", - " embedding = openai.embeddings.create(\n", - " input=content,\n", - " model=EMBEDDING_MODEL,\n", - " dimensions=EMBEDDING_DIMENSION_SIZE\n", - " ).data[0].embedding\n", + " embedding = (\n", + " openai.embeddings.create(\n", + " input=content,\n", + " model=EMBEDDING_MODEL,\n", + " dimensions=EMBEDDING_DIMENSION_SIZE,\n", + " )\n", + " .data[0]\n", + " .embedding\n", + " )\n", "\n", " collection.update_one(\n", - " {\"_id\": doc_id},\n", - " {\"$set\": {\"embedding\": embedding}},\n", - " upsert=True\n", + " {\"_id\": doc_id}, {\"$set\": {\"embedding\": embedding}}, upsert=True\n", " )\n", " except Exception as e:\n", " print(f\"Error generating embedding for document {doc_id}: {e!s}\")\n", "\n", " print(\"New embeddings generated and stored successfully.\")\n", " else:\n", - " print(\"All documents already have embeddings. No new embeddings were generated.\")\n", + " print(\n", + " \"All documents already have embeddings. No new embeddings were generated.\"\n", + " )\n", "\n", " # Verify the number of documents with embeddings\n", " docs_with_embeddings = collection.count_documents({\"embedding\": {\"$exists\": True}})\n", - " print(f\"Total documents with embeddings: {docs_with_embeddings}\")\n" + " print(f\"Total documents with embeddings: {docs_with_embeddings}\")" ] }, { @@ -782,9 +806,15 @@ ], "source": [ "# You can add this cell to verify that the data was ingested correctly\n", - "print(f\"Number of documents in {CORPUS_COLLECTION_NAME}: {db[CORPUS_COLLECTION_NAME].count_documents({})}\")\n", - "print(f\"Number of queries in {QUERIES_COLLECTION_NAME}: {db[QUERIES_COLLECTION_NAME].count_documents({})}\")\n", - "print(f\"Number of relevance judgments in {QRELS_COLLECTION_NAME}: {db[QRELS_COLLECTION_NAME].count_documents({})}\")\n", + "print(\n", + " f\"Number of documents in {CORPUS_COLLECTION_NAME}: {db[CORPUS_COLLECTION_NAME].count_documents({})}\"\n", + ")\n", + "print(\n", + " f\"Number of queries in {QUERIES_COLLECTION_NAME}: {db[QUERIES_COLLECTION_NAME].count_documents({})}\"\n", + ")\n", + "print(\n", + " f\"Number of relevance judgments in {QRELS_COLLECTION_NAME}: {db[QRELS_COLLECTION_NAME].count_documents({})}\"\n", + ")\n", "\n", "# Display a sample document from each collection\n", "print(\"\\nSample document from corpus:\")\n", @@ -813,7 +843,7 @@ "outputs": [], "source": [ "def full_text_search_aggregation_pipeline():\n", - " pass" + " pass" ] }, { @@ -845,7 +875,7 @@ " collection=collection,\n", " search_index_name=TEXT_SEARCH_INDEX,\n", " search_field=\"text\",\n", - " top_k=top_k\n", + " top_k=top_k,\n", " )\n", " return full_text_search.get_relevant_documents(query)" ] @@ -890,7 +920,9 @@ } ], "source": [ - "full_text_search(db[CORPUS_COLLECTION_NAME], \"0-dimensional biomaterials show inductive properties\")" + "full_text_search(\n", + " db[CORPUS_COLLECTION_NAME], \"0-dimensional biomaterials show inductive properties\"\n", + ")" ] }, { @@ -914,7 +946,9 @@ "from langchain_openai import OpenAIEmbeddings\n", "\n", "# Initialize embeddings model\n", - "embedding_model = OpenAIEmbeddings(model=EMBEDDING_MODEL, dimensions=EMBEDDING_DIMENSION_SIZE)\n", + "embedding_model = OpenAIEmbeddings(\n", + " model=EMBEDDING_MODEL, dimensions=EMBEDDING_DIMENSION_SIZE\n", + ")\n", "\n", "# Initialize vector store\n", "vector_store = MongoDBAtlasVectorSearch.from_connection_string(\n", @@ -922,7 +956,8 @@ " namespace=f\"{DB_NAME}.{CORPUS_COLLECTION_NAME}\",\n", " embedding=embedding_model,\n", " index_name=ATLAS_VECTOR_SEARCH_INDEX,\n", - " text_key=\"text\")" + " text_key=\"text\",\n", + ")" ] }, { @@ -1004,12 +1039,10 @@ "\n", "\n", "def hybrid_search(query: str, top_k: int = 10) -> List[Document]:\n", - " hybrid_search = MongoDBAtlasHybridSearchRetriever(\n", - " vectorstore=vector_store,\n", - " search_index_name=\"text_search_index\",\n", - " top_k=top_k\n", - " )\n", - " return hybrid_search.get_relevant_documents(query)" + " hybrid_search = MongoDBAtlasHybridSearchRetriever(\n", + " vectorstore=vector_store, search_index_name=\"text_search_index\", top_k=top_k\n", + " )\n", + " return hybrid_search.get_relevant_documents(query)" ] }, { @@ -1088,28 +1121,34 @@ "\n", "\n", "class MongoDBSearch(BaseSearch):\n", - " def __init__(self, collection, search_index_name, search_field=\"text\", batch_size=128):\n", + " def __init__(\n", + " self, collection, search_index_name, search_field=\"text\", batch_size=128\n", + " ):\n", " self.collection = collection\n", " self.search_index_name = search_index_name\n", " self.search_field = search_field\n", " self.batch_size = batch_size\n", "\n", - " def search(self,\n", - " corpus: Dict[str, Dict[str, str]],\n", - " queries: Dict[str, str],\n", - " top_k: int,\n", - " score_function: str = \"dot\",\n", - " **kwargs) -> Dict[str, Dict[str, float]]:\n", + " def search(\n", + " self,\n", + " corpus: Dict[str, Dict[str, str]],\n", + " queries: Dict[str, str],\n", + " top_k: int,\n", + " score_function: str = \"dot\",\n", + " **kwargs,\n", + " ) -> Dict[str, Dict[str, float]]:\n", " results = {}\n", " for query_id, query_text in queries.items():\n", " full_text_search = MongoDBAtlasFullTextSearchRetriever(\n", " collection=self.collection,\n", " search_index_name=self.search_index_name,\n", " search_field=self.search_field,\n", - " top_k=top_k\n", + " top_k=top_k,\n", " )\n", " documents = full_text_search.get_relevant_documents(query_text)\n", - " results[query_id] = {doc.metadata['_id']: doc.metadata['score'] for doc in documents}\n", + " results[query_id] = {\n", + " doc.metadata[\"_id\"]: doc.metadata[\"score\"] for doc in documents\n", + " }\n", " return results" ] }, @@ -1304,23 +1343,35 @@ "outputs": [], "source": [ "class MongoDBVectorSearch(BaseSearch):\n", - " def __init__(self, vector_store: MongoDBAtlasVectorSearch, embedding_model: OpenAIEmbeddings, batch_size=128):\n", - " self.vector_store = vector_store\n", - " self.embedding_model = embedding_model\n", - " self.batch_size = batch_size\n", + " def __init__(\n", + " self,\n", + " vector_store: MongoDBAtlasVectorSearch,\n", + " embedding_model: OpenAIEmbeddings,\n", + " batch_size=128,\n", + " ):\n", + " self.vector_store = vector_store\n", + " self.embedding_model = embedding_model\n", + " self.batch_size = batch_size\n", "\n", - " def search(self,\n", - " corpus: Dict[str, Dict[str, str]],\n", - " queries: Dict[str, str],\n", - " top_k: int,\n", - " score_function: str = \"dot\",\n", - " **kwargs) -> Dict[str, Dict[str, float]]:\n", - " results = {}\n", - " for query_id, query_text in queries.items():\n", - " vector_results = self.vector_store.similarity_search_with_score(query=query_text, k=top_k)\n", - " # Convert to the format expected by BEIR\n", - " results[query_id] = {str(doc.metadata.get('_id', i)): score for i, (doc, score) in enumerate(vector_results)}\n", - " return results" + " def search(\n", + " self,\n", + " corpus: Dict[str, Dict[str, str]],\n", + " queries: Dict[str, str],\n", + " top_k: int,\n", + " score_function: str = \"dot\",\n", + " **kwargs,\n", + " ) -> Dict[str, Dict[str, float]]:\n", + " results = {}\n", + " for query_id, query_text in queries.items():\n", + " vector_results = self.vector_store.similarity_search_with_score(\n", + " query=query_text, k=top_k\n", + " )\n", + " # Convert to the format expected by BEIR\n", + " results[query_id] = {\n", + " str(doc.metadata.get(\"_id\", i)): score\n", + " for i, (doc, score) in enumerate(vector_results)\n", + " }\n", + " return results" ] }, { @@ -1412,7 +1463,9 @@ ], "source": [ "print(\"Sample of retrieved results:\")\n", - "for query_id, doc_scores in list(vector_search_eval_results.items())[:5]: # First 5 queries\n", + "for query_id, doc_scores in list(vector_search_eval_results.items())[\n", + " :5\n", + "]: # First 5 queries\n", " print(f\"Query ID: {query_id}\")\n", " print(f\"Query text: {queries[query_id]}\")\n", " print(\"Top 3 retrieved documents:\")\n", @@ -1429,7 +1482,9 @@ }, "outputs": [], "source": [ - "ndcg, _map, recall, precision = vector_search_retriever.evaluate(qrels, vector_search_eval_results, vector_search_retriever.k_values)" + "ndcg, _map, recall, precision = vector_search_retriever.evaluate(\n", + " qrels, vector_search_eval_results, vector_search_retriever.k_values\n", + ")" ] }, { @@ -1509,36 +1564,45 @@ "outputs": [], "source": [ "class MongoDBHybridSearch(BaseSearch):\n", - " def __init__(self, vector_store: MongoDBAtlasVectorSearch, search_index_name: str, batch_size=128):\n", + " def __init__(\n", + " self,\n", + " vector_store: MongoDBAtlasVectorSearch,\n", + " search_index_name: str,\n", + " batch_size=128,\n", + " ):\n", " self.vector_store = vector_store\n", " self.search_index_name = search_index_name\n", " self.batch_size = batch_size\n", "\n", - " def search(self,\n", - " corpus: Dict[str, Dict[str, str]],\n", - " queries: Dict[str, str],\n", - " top_k: int,\n", - " score_function: str = \"dot\",\n", - " **kwargs) -> Dict[str, Dict[str, float]]:\n", + " def search(\n", + " self,\n", + " corpus: Dict[str, Dict[str, str]],\n", + " queries: Dict[str, str],\n", + " top_k: int,\n", + " score_function: str = \"dot\",\n", + " **kwargs,\n", + " ) -> Dict[str, Dict[str, float]]:\n", " results = {}\n", " for query_id, query_text in queries.items():\n", " hybrid_search = MongoDBAtlasHybridSearchRetriever(\n", " vectorstore=self.vector_store,\n", " search_index_name=self.search_index_name,\n", - " top_k=top_k\n", + " top_k=top_k,\n", " )\n", " documents = hybrid_search.get_relevant_documents(query_text)\n", "\n", " # Convert to the format expected by BEIR\n", " # Higher rank (lower index) gets a higher score\n", - " results[query_id] = {self._get_doc_id(doc): (len(documents) - i) / len(documents)\n", - " for i, doc in enumerate(documents)}\n", + " results[query_id] = {\n", + " self._get_doc_id(doc): (len(documents) - i) / len(documents)\n", + " for i, doc in enumerate(documents)\n", + " }\n", "\n", " return results\n", "\n", " def _get_doc_id(self, doc: Document) -> str:\n", " # Attempt to get the document ID from metadata, fallback to content hash if not available\n", - " return str(doc.metadata.get('_id', hash(doc.page_content)))\n" + " return str(doc.metadata.get(\"_id\", hash(doc.page_content)))" ] }, { @@ -1550,8 +1614,7 @@ "outputs": [], "source": [ "mongodb_hybrid_search = MongoDBHybridSearch(\n", - " vector_store=vector_store,\n", - " search_index_name=\"text_search_index\"\n", + " vector_store=vector_store, search_index_name=\"text_search_index\"\n", ")" ] }, @@ -1650,7 +1713,9 @@ }, "outputs": [], "source": [ - "ndcg, _map, recall, precision = hybrid_search_retriever.evaluate(qrels, hybrid_search_results, hybrid_search_retriever.k_values)" + "ndcg, _map, recall, precision = hybrid_search_retriever.evaluate(\n", + " qrels, hybrid_search_results, hybrid_search_retriever.k_values\n", + ")" ] }, { @@ -1733,12 +1798,14 @@ "import numpy as np\n", "\n", "\n", - "def plot_search_method_comparison(lexical_metrics, vector_metrics, hybrid_metrics, metric_names):\n", + "def plot_search_method_comparison(\n", + " lexical_metrics, vector_metrics, hybrid_metrics, metric_names\n", + "):\n", " fig, axes = plt.subplots(2, 2, figsize=(20, 16))\n", - " fig.suptitle('Comparison of Search Methods', fontsize=16)\n", + " fig.suptitle(\"Comparison of Search Methods\", fontsize=16)\n", "\n", " search_methods = information_retrieval_search_methods\n", - " colors = ['#1f77b4', '#ff7f0e', '#2ca02c'] # Blue, Orange, Green\n", + " colors = [\"#1f77b4\", \"#ff7f0e\", \"#2ca02c\"] # Blue, Orange, Green\n", "\n", " for idx, (metric_name, ax) in enumerate(zip(metric_names, axes.flatten())):\n", " lexical_data = lexical_metrics[idx]\n", @@ -1746,24 +1813,28 @@ " hybrid_data = hybrid_metrics[idx]\n", "\n", " # Ensure all dictionaries have the same keys\n", - " all_keys = set(lexical_data.keys()) | set(vector_data.keys()) | set(hybrid_data.keys())\n", + " all_keys = (\n", + " set(lexical_data.keys()) | set(vector_data.keys()) | set(hybrid_data.keys())\n", + " )\n", "\n", " x = np.arange(len(all_keys))\n", " width = 0.25\n", "\n", - " for i, (method, data) in enumerate(zip(search_methods, [lexical_data, vector_data, hybrid_data])):\n", + " for i, (method, data) in enumerate(\n", + " zip(search_methods, [lexical_data, vector_data, hybrid_data])\n", + " ):\n", " values = [data.get(k, 0) for k in all_keys]\n", - " ax.bar(x + i*width, values, width, label=method, color=colors[i])\n", + " ax.bar(x + i * width, values, width, label=method, color=colors[i])\n", "\n", - " ax.set_ylabel('Score')\n", + " ax.set_ylabel(\"Score\")\n", " ax.set_title(metric_name)\n", " ax.set_xticks(x + width)\n", - " ax.set_xticklabels(all_keys, rotation=45, ha='right')\n", + " ax.set_xticklabels(all_keys, rotation=45, ha=\"right\")\n", " ax.legend()\n", - " ax.grid(True, axis='y', linestyle='--', alpha=0.7)\n", + " ax.grid(True, axis=\"y\", linestyle=\"--\", alpha=0.7)\n", "\n", " plt.tight_layout()\n", - " plt.show()\n" + " plt.show()" ] }, { @@ -1794,7 +1865,7 @@ " lexical_search_metric_dicts,\n", " vector_search_metric_dicts,\n", " hybrid_search_metric_dicts,\n", - " metric_names\n", + " metric_names,\n", ")" ] }, @@ -1818,37 +1889,44 @@ "from datetime import datetime\n", "\n", "\n", - "def store_evaluation_results(db: Any, search_method: str, metrics: Dict[str, Dict[str, float]], additional_info: Dict[str, Any] | None = None):\n", - " \"\"\"\n", - " Store evaluation results in MongoDB.\n", - "\n", - " Args\n", - " db: MongoDB database instance\n", - " search_method: Name of the search method (e.g., 'lexical', 'vector', 'hybrid')\n", - " metrics: Dictionary containing evaluation metrics (ndcg, map, recall, precision)\n", - " additional_info: Optional dictionary for any additional information to store\n", - " \"\"\"\n", - " collection = db['evaluation_results']\n", - "\n", - " # Prepare the document to be inserted\n", - " result_doc = {\n", - " \"timestamp\": datetime.utcnow(),\n", - " \"search_method\": search_method,\n", - " \"metrics\": {}\n", - " }\n", + "def store_evaluation_results(\n", + " db: Any,\n", + " search_method: str,\n", + " metrics: Dict[str, Dict[str, float]],\n", + " additional_info: Dict[str, Any] | None = None,\n", + "):\n", + " \"\"\"\n", + " Store evaluation results in MongoDB.\n", + "\n", + " Args\n", + " db: MongoDB database instance\n", + " search_method: Name of the search method (e.g., 'lexical', 'vector', 'hybrid')\n", + " metrics: Dictionary containing evaluation metrics (ndcg, map, recall, precision)\n", + " additional_info: Optional dictionary for any additional information to store\n", + " \"\"\"\n", + " collection = db[\"evaluation_results\"]\n", + "\n", + " # Prepare the document to be inserted\n", + " result_doc = {\n", + " \"timestamp\": datetime.utcnow(),\n", + " \"search_method\": search_method,\n", + " \"metrics\": {},\n", + " }\n", "\n", - " # Add metrics to the document\n", - " for metric_name, metric_values in metrics.items():\n", - " result_doc[\"metrics\"][metric_name] = metric_values\n", + " # Add metrics to the document\n", + " for metric_name, metric_values in metrics.items():\n", + " result_doc[\"metrics\"][metric_name] = metric_values\n", "\n", - " # Add any additional information\n", - " if additional_info:\n", - " result_doc.update(additional_info)\n", + " # Add any additional information\n", + " if additional_info:\n", + " result_doc.update(additional_info)\n", "\n", - " # Insert the document\n", - " insert_result = collection.insert_one(result_doc)\n", + " # Insert the document\n", + " insert_result = collection.insert_one(result_doc)\n", "\n", - " print(f\"Evaluation results for {search_method} stored with ID: {insert_result.inserted_id}\")" + " print(\n", + " f\"Evaluation results for {search_method} stored with ID: {insert_result.inserted_id}\"\n", + " )" ] }, { @@ -1860,10 +1938,10 @@ "outputs": [], "source": [ "metadata = {\n", - " \"dataset_name\": DATASET,\n", - " \"corpus_size\": len(corpus),\n", - " \"num_queries\": len(queries),\n", - " \"num_qrels\": sum(len(q) for q in qrels.values())\n", + " \"dataset_name\": DATASET,\n", + " \"corpus_size\": len(corpus),\n", + " \"num_queries\": len(queries),\n", + " \"num_qrels\": sum(len(q) for q in qrels.values()),\n", "}\n", "\n", "information_retrieval_eval_metrics_list = [\n", @@ -1873,8 +1951,10 @@ "]\n", "\n", "# Iterate through metrics list and store evaluation results\n", - "for search_method, metrics in zip(information_retrieval_search_methods, information_retrieval_eval_metrics_list):\n", - " store_evaluation_results(db, search_method, metrics, metadata)" + "for search_method, metrics in zip(\n", + " information_retrieval_search_methods, information_retrieval_eval_metrics_list\n", + "):\n", + " store_evaluation_results(db, search_method, metrics, metadata)" ] }, { @@ -2048,7 +2128,9 @@ } ], "source": [ - "setup_vector_search_index_with_filter(db[fiqa_corpus], corpus_vector_search_index_definition)" + "setup_vector_search_index_with_filter(\n", + " db[fiqa_corpus], corpus_vector_search_index_definition\n", + ")" ] }, { @@ -2086,17 +2168,12 @@ ], "source": [ "corpus_text_index_definition = {\n", - " \"mappings\": {\n", - " \"dynamic\": True,\n", - " \"fields\": {\n", - " \"text\": {\n", - " \"type\": \"string\"\n", - " }\n", - " }\n", - " }\n", + " \"mappings\": {\"dynamic\": True, \"fields\": {\"text\": {\"type\": \"string\"}}}\n", "}\n", "\n", - "create_collection_search_index(db[fiqa_corpus], corpus_text_index_definition, TEXT_SEARCH_INDEX)" + "create_collection_search_index(\n", + " db[fiqa_corpus], corpus_text_index_definition, TEXT_SEARCH_INDEX\n", + ")" ] }, { @@ -2169,7 +2246,7 @@ " namespace=f\"{DB_NAME}.{fiqa_corpus}\",\n", " embedding=embedding_model,\n", " index_name=\"vector_index\",\n", - " text_key=\"text\"\n", + " text_key=\"text\",\n", ")\n", "\n", "vector_search = MongoDBVectorSearch(vector_store, embedding_model)\n", @@ -2186,35 +2263,37 @@ "outputs": [], "source": [ "def evaluate_search_method(search_method, method_name):\n", - " retriever = EvaluateRetrieval(search_method, score_function=\"dot\")\n", - " results = retriever.retrieve(corpus, queries)\n", - " metrics = retriever.evaluate(qrels, results, retriever.k_values)\n", - "\n", - " print(\"Sample of retrieved results:\")\n", - " for query_id, doc_scores in list(results.items())[:5]:\n", - " print(f\"Query ID: {query_id}\")\n", - " print(f\"Query text: {queries[query_id]}\")\n", - " print(\"Top 3 retrieved documents:\")\n", - " for doc_id, score in list(doc_scores.items())[:3]:\n", - " print(f\" Doc ID: {doc_id}, Score: {score}\")\n", - " print()\n", - "\n", - " print(f\"\\nResults for {method_name}:\")\n", - " ndcg, _map, recall, precision = metrics\n", - " for metric, values in zip([\"NDCG\", \"MAP\", \"Recall\", \"Precision\"], [ndcg, _map, recall, precision]):\n", - " print(f\"{metric}:\")\n", - " for k, v in values.items():\n", - " print(f\" {k}: {v:.4f}\")\n", - "\n", - " # Store results in MongoDB (assuming you've defined this function)\n", - " store_evaluation_results(db, method_name, {\n", - " \"ndcg\": ndcg,\n", - " \"map\": _map,\n", - " \"recall\": recall,\n", - " \"precision\": precision\n", - " }, {\"dataset\": \"FiQA\"})\n", + " retriever = EvaluateRetrieval(search_method, score_function=\"dot\")\n", + " results = retriever.retrieve(corpus, queries)\n", + " metrics = retriever.evaluate(qrels, results, retriever.k_values)\n", + "\n", + " print(\"Sample of retrieved results:\")\n", + " for query_id, doc_scores in list(results.items())[:5]:\n", + " print(f\"Query ID: {query_id}\")\n", + " print(f\"Query text: {queries[query_id]}\")\n", + " print(\"Top 3 retrieved documents:\")\n", + " for doc_id, score in list(doc_scores.items())[:3]:\n", + " print(f\" Doc ID: {doc_id}, Score: {score}\")\n", + " print()\n", + "\n", + " print(f\"\\nResults for {method_name}:\")\n", + " ndcg, _map, recall, precision = metrics\n", + " for metric, values in zip(\n", + " [\"NDCG\", \"MAP\", \"Recall\", \"Precision\"], [ndcg, _map, recall, precision]\n", + " ):\n", + " print(f\"{metric}:\")\n", + " for k, v in values.items():\n", + " print(f\" {k}: {v:.4f}\")\n", + "\n", + " # Store results in MongoDB (assuming you've defined this function)\n", + " store_evaluation_results(\n", + " db,\n", + " method_name,\n", + " {\"ndcg\": ndcg, \"map\": _map, \"recall\": recall, \"precision\": precision},\n", + " {\"dataset\": \"FiQA\"},\n", + " )\n", "\n", - " return [ndcg, _map, recall, precision]" + " return [ndcg, _map, recall, precision]" ] }, { @@ -2471,7 +2550,7 @@ " lexical_search_metric_dicts,\n", " vector_search_metric_dicts,\n", " hybrid_search_metric_dicts,\n", - " metric_names\n", + " metric_names,\n", ")" ] } diff --git a/notebooks/techniques/quantized_vector_ingestion_with_cohere_and_mongodb.ipynb b/notebooks/techniques/quantized_vector_ingestion_with_cohere_and_mongodb.ipynb index 60c4305..90e7c1c 100644 --- a/notebooks/techniques/quantized_vector_ingestion_with_cohere_and_mongodb.ipynb +++ b/notebooks/techniques/quantized_vector_ingestion_with_cohere_and_mongodb.ipynb @@ -818,7 +818,6 @@ }, "outputs": [], "source": [ - "\n", "# Initialize Cohere Client\n", "co = cohere.Client(COHERE_API_KEY)" ] diff --git a/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb b/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb index 31242fc..4713dcf 100644 --- a/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb +++ b/third_party/gravity9/Agentic_System_Enhanced_Contract_and_Supply_Chain_Management_for_International_Shipping.ipynb @@ -2171,7 +2171,6 @@ } ], "source": [ - "\n", "print(response)" ] }, @@ -3269,8 +3268,6 @@ }, "outputs": [], "source": [ - "\n", - "\n", "def agent_node(state: AgentState, config: RunnableConfig):\n", " print(\"----Calling Agent Node-------\")\n", " messages = state[\"messages\"]\n", diff --git a/tools/function_calling_mongodb_as_a_toolbox.ipynb b/tools/function_calling_mongodb_as_a_toolbox.ipynb index ca80893..3373fee 100644 --- a/tools/function_calling_mongodb_as_a_toolbox.ipynb +++ b/tools/function_calling_mongodb_as_a_toolbox.ipynb @@ -499,7 +499,6 @@ } ], "source": [ - "\n", "# Step 2: determine if the response from the model includes a tool call.\n", "tool_calls = response_message.tool_calls\n", "if tool_calls:\n", From 2a4be37d1c14bcc933de7175140c44f49c33da60 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 11 Dec 2024 15:17:59 -0500 Subject: [PATCH 4/5] fix order --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9bb7700..f5f9e0a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: # Ruff version. rev: v0.8.2 hooks: - - id: ruff - args: ["--fix", "--show-fixes"] - id: ruff-format exclude: notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb + - id: ruff + args: ["--fix", "--show-fixes"] \ No newline at end of file From 775656b5f9ad678dd8a1db3516e743bb30713513 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 11 Dec 2024 15:18:47 -0500 Subject: [PATCH 5/5] add newline --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f5f9e0a..b0bbe80 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,4 +19,4 @@ repos: - id: ruff-format exclude: notebooks/techniques/evaluating_information_retrival_techniques_mongondb_langchain.ipynb - id: ruff - args: ["--fix", "--show-fixes"] \ No newline at end of file + args: ["--fix", "--show-fixes"]