From 413ce22cd7340e0e7ed833c666ba78dd726df4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bilge=20Y=C3=BCcel?= Date: Fri, 26 Jan 2024 17:01:26 +0300 Subject: [PATCH] Mongodb integration page (#103) * Add MongoDB integration * Add toc config --- integrations/mongodb.md | 107 ++++++++++++++++++++++++++++++++++++++++ logos/mongodb.png | Bin 0 -> 22190 bytes 2 files changed, 107 insertions(+) create mode 100644 integrations/mongodb.md create mode 100644 logos/mongodb.png diff --git a/integrations/mongodb.md b/integrations/mongodb.md new file mode 100644 index 00000000..f4ad6b9c --- /dev/null +++ b/integrations/mongodb.md @@ -0,0 +1,107 @@ +--- +layout: integration +name: MongoDB +description: Use a MongoDB Atlas with Haystack +authors: + - name: deepset + socials: + github: deepset-ai + twitter: deepset_ai + linkedin: deepset-ai +pypi: https://pypi.org/project/farm-haystack +repo: https://github.com/deepset-ai/haystack +type: Document Store +report_issue: https://github.com/deepset-ai/haystack/issues +logo: /logos/mongodb.png +toc: true +--- + +[MongoDB](https://www.mongodb.com/) is a document database designed for ease of application development and scaling. [MongoDB Atlas](https://www.mongodb.com/atlas) is a multi-cloud database service built by people behind MongoDB. MongoDB Atlas simplifies deploying and managing your databases while offering the versatility you need to build resilient and performant global applications on the cloud providers of your choice. + +For a detailed overview of all the available methods and settings for the `MongoDBAtlasDocumentStore`, visit the Haystack [Documentation](https://docs.haystack.deepset.ai/docs/document_store#initialization). + +## Installation + +```bash +pip install farm-haystack[mongodb] +``` + +## Usage + +To use MongoDB Atlas as your data storage for your Haystack LLM pipelines, you must have a running database at MongoDB Atlas. For details, see [Get Started with Atlas](https://www.mongodb.com/docs/atlas/getting-started/). + +Once your database is set, you can initialize a `MongoDBAtlasDocumentStore` for Haystack with required configurations: + +```python +from haystack.document_stores.mongodb_atlas import MongoDBAtlasDocumentStore + +ds=MongoDBAtlasDocumentStore( + mongo_connection_string="mongodb+srv://{mongo_atlas_username}:{mongo_atlas_password}@{mongo_atlas_host}/?{mongo_atlas_params_string}", + database_name="database_name", + collection_name="collection_name", +) +``` + +### Writing Documents to MongoDBAtlasDocumentStore + +To write documents to your `MongoDBAtlasDocumentStore`, create an indexing pipeline, or use the `write_documents()` function. +For this step, you may make use of the available [FileConverters](https://docs.haystack.deepset.ai/docs/file_converters) and [PreProcessors](https://docs.haystack.deepset.ai/docs/preprocessor), as well as other [Integrations](/integrations) that might help you fetch data from other resources. Below is an example indexing pipeline that indexes your Markdown files into a MongoDB Atlas instance. + +#### Indexing Pipeline + +```python +from haystack import Pipeline +from haystack.document_stores.mongodb_atlas import MongoDBAtlasDocumentStore +from haystack.nodes import MarkdownConverter, PreProcessor + +document_store=MongoDBAtlasDocumentStore( + mongo_connection_string="mongodb+srv://{mongo_atlas_username}:{mongo_atlas_password}@{mongo_atlas_host}/?{mongo_atlas_params_string}", + database_name="database_name", + collection_name="collection_name", + embedding_dim=1536 +) +converter = MarkdownConverter() +preprocessor = PreProcessor() + +indexing_pipeline = Pipeline() +indexing_pipeline.add_node(component=converter, name="PDFConverter", inputs=["File"]) +indexing_pipeline.add_node(component=preprocessor, name="PreProcessor", inputs=["PDFConverter"]) +indexing_pipeline.add_node(component=document_store, name="DocumentStore", inputs=["PreProcessor"]) + +indexing_pipeline.run(file_paths=["filename.pdf"]) +``` + +### Query Pipeline + +Once you have documents in your `MongoDBAtlasDocumentStore`, it's ready to be used in any Haystack pipeline. For example, below is a pipeline that makes use of a custom prompt that is designed to answer questions for the retrieved documents. + +```python +from haystack import Pipeline +from haystack.document_stores.mongodb_atlas import MongoDBAtlasDocumentStore +from haystack.nodes import AnswerParser, EmbeddingRetriever, PromptNode, PromptTemplate + +document_store=MongoDBAtlasDocumentStore( + mongo_connection_string="mongodb+srv://{mongo_atlas_username}:{mongo_atlas_password}@{mongo_atlas_host}/?{mongo_atlas_params_string}", + database_name="database_name", + collection_name="collection_name" +) + +retriever = EmbeddingRetriever(document_store = document_store, + embedding_model="sentence-transformers/multi-qa-mpnet-base-dot-v1") +prompt_template = PromptTemplate(prompt = """"Answer the following query based on the provided context. If the context does + not include an answer, reply with 'I don't know'.\n + Query: {query}\n + Documents: {join(documents)} + Answer: + """, + output_parser=AnswerParser()) +prompt_node = PromptNode(model_name_or_path="gpt-4", + api_key="YOUR_OPENAI_KEY", + default_prompt_template=prompt_template) + +query_pipeline = Pipeline() +query_pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) +query_pipeline.add_node(component=prompt_node, name="PromptNode", inputs=["Retriever"]) + +query_pipeline.run(query = "What is MongoDB Atlas?", params={"Retriever" : {"top_k": 5}}) +``` \ No newline at end of file diff --git a/logos/mongodb.png b/logos/mongodb.png new file mode 100644 index 0000000000000000000000000000000000000000..7b6492d0f6ee78c459c993577d566932627c34ac GIT binary patch literal 22190 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 z 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